您的位置:首页 > Web前端 > JavaScript

JavaScript的继承--原型链

2016-06-13 13:04 435 查看
JavaScript描述了原型链的概念,并将原型链作为实现继承的主要方法。

基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法

构造函数、原型和实例

简单回顾一下构造函数、原型与实例之间的关系:每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针:
constructor
,而实例都包含一个指向原型对象的内部指针:
__proto__




原型链继承

假如,我们让原型对象等于另一个类型的实例,结果会怎么样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。

接下来我们用一个例子说明原型链继承,在这个例子中,定义了两个类型:SuperType和SubType,这两个类型分别定义了一个属性和一个方法。最后的结果SubType继承了SuperType, SubType的instance可以通过原型链访问SuperType的方法和属性。

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();
console.log(instance.getSuperValue);    //true


原型链图解如下:



红色标识的线条就是instance–>SubType–>SuperType的原型链。

原型链继承的方式是通过创建一个SuperType的实例并且将其赋值给SubType.prototype来实现的,本质是重写原型对象。

将SubType的原型对象设置为SuperType的实例对象,从而使得SubType的原型对象可以通过原型链找到SuperType的原型对象(按照红线查找),通过原型链,instance这个SubType的实例对象可以访问SubType和SuperType的所有属性和方法。

注意事项一: 如果某一个原型对象(SubType prototype)有替换原型的操作,那么针对该原型对象的添加属性或者方法的操作必须位于替换原型操作之后。如果不这么做,那么针对该原型对象所添加的属性和方法都会在替换原型操作的时候作废,因为之前的原型对象(SubType prototype)作废了,取而代之的是替换原型(SuperType instance)。

注意事项二此时instance.constructor属性访问的是SuperType prototype的constructor,因此其指向的是SuperType,这是因为SubType.prototype被重写了的缘故。instance.constructor的查找路线为:

1. 查找instance实例 —– 没有查找到

2. 查找SubType的原型对象 —— 没有查找到

3. 查找SuperType的原型对象 ——- 找到,指向SuperType

实例与原型之间的关系

实例是原型链上所有原型的实例

console.log(instance instanceof SuperType);    //true
console.log(instance instanceof SubType);      //true


原型链上的所有原型都是实例的原型

console.log(SuperType.prototype.isPrototypeof(instance));  //true
console.log(SubType.prototype.isPrototypeof(instance));    //true


原型链的问题

问题一:

在通过替换原型的方式来实现继承时,原型实际上会变成另外一个类型的实例,于是,原先的实例属性也就顺理成章地变成了现在的原型属性。从图解中可以清楚地看出SuperType的实例属性变为了SubType的原型属性。这样就会导致不该被所有实例共享的属性被原型共享了,从本例中就是对于SubType而言,从SuperType那里继承过来的property属性不再是一个实例属性,而是一个原型属性了。

问题二:

在创建子类型的实例的时候,不能向超类构造函数传递参数。确切地说是没有办法在不影响所有对象实例的情况下,向超类构造函数传递参数。

因为原型链的问题,因此原型链的继承方式很少单独使用,通常是配合其他方式一起使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 继承 原型