0 0今天看到原型链。。又一次懵逼。。果然每次看都有新体验啊。。
之前看prototype看的一知半解。今天又花了点时间重新理解了下。。而且最近睡眠不足。。一半时间瞪着书是懵逼的,一点看不懂。
首先要知道,只要创建了一个新的函数,这个函数就会获得一个prototype属性,并且拥有了一个原型对象。
这个函数的prototype指向原型对象,原型对象会拥有一个constructor,constructor指针指向这个函数
把这一类没有显示new的函数暂成为构造函数。对于构造函数,函数与其Prototype就是这样的关系。
我们把
<span style="font-size:14px;color:#333333;"><span style="font-size:14px;"><span style="font-size:14px;">var a = new Person();</span></span></span>
a这样的对象成为实例。实例被创建之后,会有一个属性__proto__(原为[[prototype]],脚本中以__proto__访问)。这个属性中存放指向构造函数原型(Person Prototype)的指针。
对于a实例的属性访问,可以通过__proto__访问到父类的属性(????)。并且由于指向Prototype对象,就拥有了constructor,这样实例可以访问到构造函数对象。
因此实例和构造函数没有直接关系
然后祭出这张图:
对于构造函数Animal,当其作为构造函数,有prototype属性,指向Prototype原型对象。但是同时,Animal是通过Function方法创建的,所以是Function的实例,因此有__proto__属性,指向Function的prototype。同理Function对象是由Function方法产生的......最终,Function的prototype指向Object的原型,Object的原型中的__proto__指向null。
所有的prototype都是Object产生的,所以Prototype原型对象的__proto__都指向Object的原型
因此在继承的时候,如:
function aa(){this.age = 12;}
function bb(){this.age = 11;}
aa.prototype.age = 10;
bb.prototype.age = 9;
bb.prototype = new aa();
var cc = new bb();
console.log(cc.age);
这时候输出11,如果删掉bb.age,就输出12,如果再删掉这个属性,输出10,再删就没有了。。
原因就是在访问cc的时候,由于cc是bb的实例,所以访问属性的时候,先访问实例,实例没有就查看原型。由于这时候bb的原型指向了aa,就查看aa中是否有该属性,没有就查看aa的原型对象。
**********************************************************************
prototype就相当于C++中的静态全局变量。。?(我居然这么久没用C++了TAT)所有的Function实例共享一份Prototype。所以prototype使用最大问题之一就是属性的共享。如果共享的是值类型,那就没有关系,因为只是数值的传递。但是如果是引用类,比如数组,那么传递的就是指针。再修改的时候
,值类型修改的是数值,而引用类修改的就是原数据了。