原型鏈
思想
利用原型讓一個引用型別繼承另一個引用型別的屬性和方法。
方式
將子類的原型設定為父類的例項。
實現
function SuperType() {}
function SubType() {}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
複製程式碼
問題
- 問題1。最主要的問題來自包含引用型別值的原型。包含引用型別值的原型屬性會被所有例項共享。
function SuperType() {
this.number = [1, 2, 3];
}
function SubType() {}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
let ins1 = new SubType();
let ins2 = new SubType();
ins1.number[0] = 11;
console.log(ins2.number); // [11, 2, 3]
複製程式碼
- 問題2。在建立子型別的例項時,不能向超型別的建構函式傳遞引數。實際上,應該說時沒有辦法在不影響所有物件例項的情況下,給超型別的建構函式傳遞引數。
借用建構函式
思想
在子型別的建構函式內部呼叫超型別的建構函式。
實際上就是將超型別的程式碼在子類中執行一遍,使子型別擁有超型別的屬性的副本。
實現
function SuperType() {
this.num = [1, 2, 3];
}
function SubType() {
// 繼承 SuperType
// 注意需要用 call 或 apply
SuperType.call(this);
}
複製程式碼
比較
-
相對於原型鏈繼承,借用建構函式不存在引用型別的原型屬性被所有例項共享的問題,因為每個例項都有超類中屬性的副本。
-
可以向超型別建構函式傳遞引數
問題
- 在超型別的原型中定義的方法,對子型別是不可見的。
組合繼承
思想
結合原型鏈和借用建構函式兩種方式。
使用原型鏈實現對原型屬性和方法的繼承,使用借用建構函式實現對例項屬性的繼承。
實現
function SuperType() {}
function SubType() {
// 借用建構函式繼承
SuperType.call(this);
}
// 原型鏈繼承
SubType.prototype = SuperType;
SubType.prototype.constructor = SubType;
複製程式碼
參考
- 《JavaScript 高階程式設計》(第3版)