[TOC]

到底什么是JS原型

转载自blog:到底什么是JS原型

话说在前头,去网上查问很多对于JS原型的解释的文章,其中有80%看了都会不知所云,大多数对于JS原型的解释的文章或者视频,都疏忽了很多读者对一些专业名词、概念是不把握的,或者你说的一句话,就能够绕晕读者,导致大家走了很多很多弯路。在这里先分享我查到的一篇对于JS原型的解释,是最通俗易懂的,地址。

一、首先大家在对JS原型进行解释的时候,会波及两个概念:构造函数、原型对象

1.构造函数:艰深的一句话说,就是你在script标签外面申明的那个函数:

<body><script>    function students() {        /* 我就是构造函数 */     } </script></body>

2.原型对象:在申明了一个函数之后,浏览器会主动依照肯定的规定创立一个对象,这个对象就叫做原型对象。这个原型对象其实是贮存在了内存当中。

3.在申明了一个函数后,这个构造函数(申明了的函数)中会有一个属性prototype,这个属性指向的就是这个构造函数(申明了的函数)对应的原型对象;原型对象中有一个属性constructor,这个属性指向的是这个构造函数(申明了的函数)。上面一张图能够很简略了解:

二、应用构造函数创建对象

咱们的构造函数应用new来创建对象的时候,就像上面这样:

<body><script>    function students() {        /* 我就是构造函数 */     }         var stu = new students();</script></body>

此时,stu就是那个构造函数students创立进去的对象,这个stu对象中是没有prototype属性的,prototype属性只有在构造函数students中有,请看图!

能够看出,构造函数students中有prototype属性,指向的是students对应的原型对象;
而stu是构造函数students创立进去的对象,他不存在prototype属性,所以在调用prototype的时候的构造是undefined,但stu有一个__proto__属性,stu调用这个属性能够间接拜访到构造函数students的原型对象(也就是说,stu的__proto__属性指向的是构造函数的原型对象),请看图。

阐明(援用后面提到的文章的内容,因为很重要):

从下面的代码中能够看到,创立stu对象尽管应用的是students构造函数,然而对象创立进去之后,这个stu对象其实曾经与students构造函数没有任何关系了,stu对象的__proto__属性指向的是students构造函数的原型对象。

如果应用new students()创立多个对象stu1、stu2、stu3,则多个对象都会同时指向students构造函数的原型对象。

咱们能够手动给这个原型对象增加属性和办法,那么stu1,stu2,stu3…这些对象就会共享这些在原型中增加的属性和办法。

如果咱们拜访stu中的一个属性name,如果在stu对象中找到,则间接返回。如果stu对象中没有找到,则间接去stu对象的__proto__属性指向的原型对象中查找,如果查找到则返回。(如果原型中也没有找到,则持续向上找原型的原型—原型链)。

如果通过stu对象增加了一个属性name,则stu对象来说就屏蔽了原型中的属性name。 换句话说:在stu中就没有方法拜访到原型的属性name了。

通过stu对象只能读取原型中的属性name的值,而不能批改原型中的属性name的值。 stu.name = “李四”; 并不是批改了原型中的值,而是在stu对象中给增加了一个属性name。

请看上面代码(在下面提到的文章中做了小幅度批改,更有助于了解)

<body>    <script type="text/javascript">        function students () {                }        // 能够应用students.prototype 间接拜访到原型对象        //给students函数的原型对象中增加一个属性 name并且值是 "张三"        students.prototype.name = "张三";        students.prototype.age = 20;        var stu = new students();        /*            拜访stu对象的属性name,尽管在stu对象中咱们并没有明确的增加属性name,然而            stu的__proto__属性指向的原型中有name属性,所以这个中央能够拜访到属性name            就值。            留神:这个时候不能通过stu对象删除name属性,因为只能删除在stu中删除的对象。        */        alert(stu.name);  // 张三             var stu1 = new students();        alert(stu1.name);  // 张三  都是从原型中找到的,所以一样。             alert(stu.name === stu1.name);  // true             // 因为不能批改原型中的值,则这种办法就间接在stu中增加了一个新的属性name,而后在stu中无奈再拜访到        //原型中的属性。        stu.name = "李四";        alert(stu.name); //李四        // 因为stu1中没有name属性,则对stu1来说依然是拜访的原型中的属性。            alert(stu1.name);  // 张三      </script></body>

三、与原型无关的几个办法

  1. prototype属性

prototype 存在于构造函数中 (其实任意函数中都有,只是不是构造函数的时候prototype咱们不关注而已) ,他指向了这个构造函数的原型对象。

  1. constructor属性

    constructor属性存在于原型对象中,他指向了构造函数

如上面代码:

<script type="text/javascript">    function students () {    }    alert(students.prototype.constructor === students); // true</script>

<span style="color:#ff0000;">咱们依据须要,能够students.prototype 属性指定新的对象,来作为students的原型对象。然而这个时候有个问题,新的对象的constructor属性则不再指向students构造函数了。
</span>

<span style="color:#ff0000;">
</span>

3.__proto__ 属性(留神:左右各是2个下划线)

用构造方法创立一个新的对象之后,这个对象中默认会有一个属性__proto__, 这个属性就指向了构造方法的原型对象。

到此为止,JS的原型的根底就是这些了,如果有看不懂的请间接评论在上面,有对于JS原型更深刻的一些用法,理论用到的时候再进行分享。

本文由mdnice多平台公布