带你看懂JavaScript的继承(二) 原型链代码详解

上一期中,我们给出了一段解释原型链的代码,同时也实现了简单的继承。下面我们继续来解读代码用相关原型链的知识。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function SuperType(){
this.property = true;
}

SuperType.prototype.getSuperValue = function(){
return this.property;
}

function SubType(){
this.subproperty = false;
}
//实现了SubType继承SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function(){
return this.subproperty;
}
var instance = new SubType();
alert(instance.getSuperValue()) //true

我们定义了两个类型:SuperType和SubType。每个类型分别有一个属性和一个方法。SubType继承了SuperType。通过创建SuperType的实例,并将实例赋给SubType.prototype来实现的。其本质是重写SubType的原型对象。所以原来存在于SuperType实例中的所有属性和方法现在也存在于SubType.prototype中了。然后我们又向SubType.prototype中添加了一个新的方法。

关系图:
Alt text

通过图我们可以看出,我们没有使用Subtype的默认的原型,而是将其替换为SuperType的实例。于是,新的原型不仅有作为一个SuperType实例的全部属性和方法,而且这个实例内部还有一个指针指向了SuperType原型的指针。简单地说,形成了一个链条:instance.prototype–>SubType.prototype–>SuperType.prototype.这就是我们通俗意义上的原型链。instance可以顺着原型链一直追溯到到SuperType。我们可以向这个链条上加入更多地连环,这个链条就会越来越长,但是末端的节点总能顺着原型链找到祖先的任何一个节点,从而调用其方法和属性。

这里有一个难点作为本期扩展的知识点。此时的instance的constructor指向的是谁呢?当然指向的是SuperType。那是为什么呢?有的人会说SubType.prototype的constructor被重写了。其实这个说法并不准确。准确的说法是SubType的原型指向了另一个对象SuperType的原型,而这个原型对象的constructor属性指向的是SuperType。