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中最常用的一种继承模式。可以作为模板掌握。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。