在 JavaScript 中,構造函數繼承可以通過 原型鏈 和 構造函數調用 實現。以下是 ES5 和 ES6 的實現方式:
ES5 實現方式
關鍵步驟
- 繼承實例屬性:在子構造函數中調用父構造函數的
call
/apply
,綁定this
。 - 繼承原型方法:將子構造函數的原型設置為父構造函數的實例,形成原型鏈。
- 修復
constructor
:修正子構造函數原型的constructor
指向自身。
代碼實現
// 父構造函數
function Parent(name) {this.name = name; // 實例屬性
}
Parent.prototype.sayName = function() { // 原型方法console.log("Parent name:", this.name);
};// 子構造函數
function Child(name, age) {// 1. 繼承父構造函數的實例屬性Parent.call(this, name); // 綁定 this,傳遞參數this.age = age;
}// 2. 繼承父構造函數的原型方法
Child.prototype = Object.create(Parent.prototype); // 建立原型鏈// 3. 修復 constructor 指向
Child.prototype.constructor = Child;// 子類新增原型方法
Child.prototype.sayAge = function() {console.log("Child age:", this.age);
};// 測試
const child = new Child("Alice", 10);
child.sayName(); // Parent name: Alice
child.sayAge(); // Child age: 10
關鍵點
Parent.call(this)
:確保子類實例繼承父類的實例屬性。Object.create(Parent.prototype)
:避免直接調用new Parent()
(可能觸發父類副作用),僅繼承原型方法。- 修復
constructor
:防止原型鏈混亂(否則child.constructor
會指向Parent
)。
ES6 實現方式
ES6 通過 class
和 extends
簡化繼承,底層依然基于原型鏈。
代碼實現
// 父類
class Parent {constructor(name) {this.name = name; // 實例屬性}sayName() { // 原型方法console.log("Parent name:", this.name);}
}// 子類繼承父類
class Child extends Parent {constructor(name, age) {super(name); // 必須調用 super(),繼承父類實例屬性this.age = age;}sayAge() { // 子類原型方法console.log("Child age:", this.age);}
}// 測試
const child = new Child("Bob", 12);
child.sayName(); // Parent name: Bob
child.sayAge(); // Child age: 12
關鍵點
extends
:建立原型鏈,自動繼承父類原型方法。super()
:必須優先調用,相當于Parent.call(this)
,負責初始化父類實例屬性。- 無需手動維護原型鏈和
constructor
:語法糖自動處理。
對比總結
特性 | ES5 | ES6 |
---|---|---|
語法 | 手動操作原型鏈和構造函數調用 | 使用 class 和 extends 語法糖 |
實例屬性繼承 | 通過 Parent.call(this) | 通過 super() |
原型方法繼承 | 手動設置 Child.prototype = Object.create() | 自動通過 extends 實現 |
constructor 修復 | 需手動修正 Child.prototype.constructor | 自動維護 |
靜態方法繼承 | 需手動處理(如 Child.__proto__ = Parent ) | 自動繼承 |
注意事項
- ES6 的
super
:- 必須在子類
constructor
中優先調用,否則報錯。 super
在方法中可調用父類原型方法(如super.sayName()
)。
- 必須在子類
- 靜態方法繼承:
- ES5 中需手動設置
Child.__proto__ = Parent
。 - ES6 中通過
extends
自動繼承父類的靜態方法。
- ES5 中需手動設置
通過 ES5 顯式原型鏈操作 或 ES6 的 class
語法,均可實現構造函數繼承。ES6 的語法更簡潔且更接近傳統面向對象語言,推薦優先使用。