原型链、prototype、_proto_那些事
一、概念
1、Prototype:每一个构造函数都有一个原型对象,这个对象就是Prototype。这个构造函数如何找到他的原型对象呢?每个构造函数都会有一个prototype属性,指向它的原型对象。这就是相当于构造函数的一个属性,注意它不是原型链中的那个关键的链子。
2、constructor:每个原型对象都包含一个指向构造函数的指针,这个指针就是constructor,从而实现了构造函数和其原型之间的双向绑定。a.prototype.constructor指向a
3、_proto _ :所有的对象都含有_proto_标签,a对象有_proto_标签,a.prototype也有_proto_标签。你可以简单的理解为指针。它的作用就是原型链形成的关键,靠它串联起来,它会是指向当前对象的构造函数的原型对象。红宝书中也用[[prototype]]表示,是一个意思
举个栗子:
二、Function.prototype比较特殊
如图中所示,右边一列的原型链跟上面讲的没什么两样。但是左边这三个就神奇了,我们都知道所有的原型链的顶端最后都指向Object.prototype。但是他们的构造函数,像Function、Array甚至Object都指向Function.prototype。其实这也好理解,刚刚也说了嘛,他们都是构造函数,既然是函数,当然会乖乖的归在Function.prototype下了。当然最后仍然归一到了Object.prototype!!
也就是说所有的构造函数的_ _proto_ _如果没有改写的话都是指向Function.prototype。一个函数的constructor都是Function,具体原因看完下面第三部分就明白了。
三、红宝书的例子详解
function SuperType(){
this.property=true;
}
SuperType.prototype.getSuperValue=function(){
return this.property;
};
function SubType(){
this.subproperty=false;
}
//继承了SuperType
SubType.prototype=new SuperType();
SubType.prototype.getSubValue=function(){
return this.subproperty;
};
var instance=new SubType();
alert(instance.getSuperValue());
这个例子是红宝书原型链继承的一个例子,书中也画了图解。作为初学者,可能会犯很多错误,下图就是之前我自以为是的“完善的图”,但其实都是画蛇添足。
下面是错误示例!!!
注意:
上图有很多错误,下面我从上到下的顺序一一指正出来。
-
1、SuperType的_ proto _属性不是null,而是Function.prototype。
-
2、SubType的_ proto _属性不是null,而是Function.prototype.
-
3、SuperType.prototype的_ proto _是最指向Object.prototype,这个是因为手抖,箭头下滑了。
-
4、SubType.prototype没有constructor属性。这是为什么呢?因为在代码运行到
SubType.prototype=new SuperType();这步之前还是有constructor属性的并且指向SubType。但是这条语句执行完后,SubType的prototype被重写了,执行完SuperType构造函数得到了一些属性和方法。之前自己的属性方法全部没了。所以现在SubType.prototype并没有constructor,它沿着原型链向上查找,查找到SuperType.prototype才找到。
所以你执行SubType.prototype.constructor的返回值是SuperType,但是SubType.prototype.hasOwnProperty("constructor")返回值是false。
-
5、instance.prototype是不存在的,因为只有构造函数具有原型对象。instance只是一个实例,是一个Object。
-
6、instance.constructor也不存在,理由因为只有prototype原型对象具有constructor属性。instance.constructor返回值是SuperType构造函数,那是因为instance没有这个属性,它向上查找一直查找到SuperType.prototype才找到。
正确的图解