JavaScript核心-继承-原型链

继承是面向对象的编程的一大特性,很多OO语言都支持两种继承方式:接口继承和实现继承。在ECMAScript中,由于函数没有签名,所以无法实现接口继承,只有实现继承。

实现继承主要是依靠原型链来实现的。


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


再回顾一下原型对象的用途:用途是包含可以由特定类型的所有实例共享的属性和方法。


原型对象也是一个简单的对象,如果我们让一个原型对象等于另一个类型的实例,也就是说可以让一个原型对象的原型是一个非null的引用,那么此时的原型对象将包含一个指向另一个原型的指针。加入另一个原型又是另一类型的实例,那上述关系依然成立,如此层层递进,就构成了原型链。


总的来说,原型链就是用来实现继承和共享属性的有限对象链。


当我们读取一个实例的属性时,首先会在实例中搜索该属性。如果没有找到该属性,就会在实例的原型中继续搜索该属性。当我们利用了原型链来实现继承时,如果在实例的原型中还没找到该属性,就会在原型的原型中继续寻找,并以此类推,遍历整个原型链。如果遍历了整个原型链还是没找到这个属性的话,就返回undefined值。


因为所有的引用类型都默认继承自Object,所有默认原型都包含一个内部指针,指向Object.Prototype。这也是所有自定义类型都会继承toString(),valueOf()等默认方法的根本原因。


使用原型链来继承会存在以下两个问题:

1.包含引用类型值的原型属性会被所有的实例所共享。这也是我们一般在构造函数中,而不是原型中定义属性的原因。在通过原型来实现继承时,原型实际上会变成另一个类型的一个实例,于是这个实例的属性也就变成了现在原型的属性了。

2.在构造子类型的实例时,不能像超类型的构造函数中传递参数。


解决以上问题的一个方法就是采用组合继承,就是将原型链和借用构造函数的技术组合到一起的一种继承模式。

思路就是使用原型链实现对原型属性和方法(主要是方法)的继承,而通过借用构造函数来实现对实例属性的继承。下面是例子:

function SuperType(name){
	this.name = name;
	this.colors = ["red","yellow"];
}

SuperType.prototype.sayName = function(){
	alert(this.name);
};

function SubType(name,age){
	//借用父类的构造函数,这样SubType的实例中就有了name和colors这两个实例属性,这两个属性就是每个实例独有的了
	<span style="color:#FF0000;">SuperType.call(this,name);</span>
	this.age = age;
}

//继承方法
SubType.prototype = new SuperType();
//这是把SubType的constructor属性改回来,创建SubType实例时调用SubType的构造函数
<span style="color:#FF0000;">SubType.prototype.constructor = SubType;</span>

//在SubType的新原型上添加一个方法
SubType.prototype.sayAge = function(){
	alert(this.age);
};

var instance1 = new SubType("zhu",24);
instance1.colors.push("black");
alert(instance1.colors);  //red,yellow black
instance1.sayName();  //zhu
instance1.sayAge(); 	//24

var instance2 = new SubType("li",23);
instance2.colors.push("blue");
alert(instance2.colors);  //red,yellow blue
instance2.sayName();  //li
instance2.sayAge(); 	//23
上面的代码实例化了两个SubType的实例instance1和instance2,它们既拥有了自己的是、属性,包括colors,同时也有了相同的方法sayName()。

这种组合继承避免了原型链和借用构造函数的确定,融合了其优点,也是JavaScript中最常用的一种继承模式。可以作为模板掌握。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。