組合繼承
前面兩篇我們了解到:原型鍊繼承存在着引用類型問題,而借用構造函數又無法實作函數複用和原型方法繼承的問題。那麼能不能把兩者結合一下,取其精華,棄其糟粕?答案是肯定的。那就是接下來我們要介紹的組合繼承。
組合繼承有時候也叫做僞經典繼承,指的是将原型鍊和借用構造函數的技術組合到一起,進而發揮二者之長的一種繼承模式。其思路就是使用原型鍊實作對原型屬性和方法的繼承。而通過借用構造函數來實作對執行個體屬性的繼承。這樣既通過在原型上定義方法實作函數複用,又能保證每個執行個體都有它自己的屬性。下面來看一個例子
function Father(name){
this.name = name;
this.colors = ['red','pink','green'];
}
Father.prototype.sayName = function(){
console.log(this.name)
}
function Son(name, age){
//屬性繼承
Father.call(this, name);
this.age = age;
}
//方法繼承
Son.prototype = new Father();
Son.prototype.sayAge = function(){
console.log(this.age);
}
var son1 = new Son('Alvin', 28);
son1.colors.push('yellow');
console.log(son1.colors); // red,pink,green,yellow
son1.sayName(); //Alvin
son2.sayAge(); //28
var son2 = new Son('Semon', 29);
console.log(son2.colors);//red,pink,green
son2.sayName(); //Semon
son2.sayAge(); //29
在這個例子中,Father構造函數定義了兩個屬性:name和colors, Father的原型定義了一個方法sayName()。Son構造函數在調用Father的構造函數時傳入了name參數,緊接着又定義了它自己的屬性age。然後将Father的執行個體指派給Son的原型,然後又在該新原型上定義了方法sayAge()。這樣一來就可以讓兩個不同的Son執行個體既分别擁有自己的屬性,又可以使用相同的方法了。
組合繼承避免了原型鍊和借用構造函數的缺陷,融合了它們的有點,成為JavaScript中最長用的繼承模式。