不同点:原型链继承中子类构造函数的原型(prototype)是父类的一个实例(我们真正需要继承的东西可能存在于父类构造函数的原型中,也可能存在于直接指向的父类实例中),而原型式继承中子类构造函数的原型是一个已有的对象,可以说直接就是父类。
五. 寄生式继承
寄生式继承可以说是原型式继承的变体,它对原型式继承进行了封装,使得创建子类实例只依赖于一个函数。
看如下代码:
var obj = { color: 'red', getColor: function(){ alert(this.color); }, }; function getChild(obj){ function func(){} func.prototype = obj; return new func(); } /*-------以上是原型式继承的代码----------*/ function betterGetChild(obj,size){ var temp_obj = getChild(obj); temp_obj.size = size; temp_obj.getSize = function(){ return this.size; }; return temp_obj; } var demo = betterGetChild(obj,200);
六. 寄生组合式继承
寄生组合式是组合继承加上原型式继承的应用。由于组合式继承中子类构造函数的原型指向父类的一个实例而非父类构造函数的原型,会导致设置子类构造函数的原型时对父类的构造函数进行一次额外的调用。所以在寄生式组合继承中,借用原型式继承的思想,将父类构造函数的原型当作一个已有对象,让子类构造函数的原型直接指向它。
看如下代码:
function getChild(obj){ function func(){} func.prototype = obj; return new func(); //调用构造函数 } /*-------以上是原型式继承的代码----------*/ function Parent(color){ this.color = color; } Parent.prototype.getColor = function(){ alert(this.color); }; function Child(color,size){ Parent.call(this,color); //调用构造函数 this.size = size; } //Child.prototype直接指向一个__proto__指向Parent.prototype的实例 Child.prototype = getChild(Parent.prototype); Child.prototype.getSize = function(){ alert(this.size); };
其实严格来说,这种方式也调用了两次构造函数,但是其中一次构造函数的调用是对一个空函数的调用,而不是两次都调用父类的构造函数。
在组合继承中,在子类的原型中其实还保存有父类的没有定义在原型中的属性(由于子类构造函数的原型是父类的一个实例),只不过是子类构造函数在借用父类构造函数在当前实例中生成了覆盖原型中那些属性的属性。而寄生式组合继承中,根本不会产生那些冗余数据。
人们普遍认为寄生时组合继承是最理想的继承方式。
更多关于JavaScript相关内容还可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》