面向物件(繼承)--寄生組合式繼承06
阿新 • • 發佈:2018-12-14
還記得組合繼承嗎,回憶一下
function SuperType(name) { this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function () { alert(this.name); }; function SubType(name, age) { SuperType.call(this, name); // 第二次呼叫 SuperType() this.age = age; } SubType.prototype = new SuperType(); // 第一次呼叫 SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function () { alert(this.age); };
在第一次呼叫 SuperType 建構函式:SubType.prototype 會得到兩個屬性: name 和 colors ;它們都是 SuperType 的例項屬性,只不過現在位於 SubType 的原型中。
在第二次呼叫 SuperType 建構函式:當呼叫 SubType 建構函式時,就會呼叫 SuperType 建構函式。在新物件上建立了例項屬性 name 和 colors 。這兩個屬性就遮蔽了原型中的兩個同名屬性。
問題就出在有兩組 name 和 colors 屬性:一組在例項上,一組在 SubType 原型中,請看下圖就會一目瞭然
使用寄生組合式繼承可以解決這個問題,寄生組合式繼承的本質是使用寄生式繼承來繼承超型別的原型,然後再將結果指定給子型別的原型。
先回憶一下object()函式
function object(o){
function F(){}
F.prototype = o;
return new F();
}
寄生組合式繼承的基本模式如下所示。
function inheritPrototype(subType, superType) { var prototype = object(superType.prototype); //建立物件 prototype.constructor = subType; //增強物件 subType.prototype = prototype; //指定物件 }
在函式內部,第一步是建立超型別原型的一個副本。第二步是為建立的副本新增 constructor 屬性,從而彌補因重寫原型而失去的預設的 constructor 屬性。最後一步,將新建立的物件(即副本)賦值給子型別的原型。
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function () {
alert(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function () {
alert(this.age);
};
這個例子的高效率體現在它只調用了一次 SuperType 建構函式,並且因此避免了在 SubType.prototype 上面建立不必要的、多餘的屬性。與此同時,原型鏈還能保持不變;