一、原型鏈繼承
原型鏈繼承是 JavaScript 中最基本的繼承方式。在原型鏈繼承中,子類對象的原型指向其父類對象,通過這樣的方式實現了繼承。
代碼示例:
function Parent() {
this.name = "parent";
}
Parent.prototype.getName = function () {
console.log(this.name);
}
function Child() {}
Child.prototype = new Parent();
var child = new Child();
child.getName(); // "parent"
實現原理:當訪問 child.getName() 時,JavaScript 引擎會先查找 child 對象身上是否有此方法,沒有則去原型鏈中的 Parent.prototype 上查找,找到了則執行,否則繼續向上查找,直到找到 Object.prototype。
優點:代碼簡單易懂,易於實現。
缺點:原型鏈繼承會將父類的引用類型屬性共享給所有子類實例,容易造成意外修改,同時無法向父類構造函數傳遞參數。
二、借用構造函數繼承(經典繼承)
借用構造函數繼承是在子類構造函數內部調用父類構造函數,並通過 call 或 apply 方法將父類實例綁定到子類實例上,從而實現繼承。
代碼示例:
function Parent(name) {
this.name = name;
}
function Child(name) {
Parent.call(this, name);
}
var child = new Child("child");
console.log(child.name); // "child"
實現原理:通過在子類構造函數內部調用父類構造函數,並綁定 this,從而實現了繼承。借用構造函數繼承避免了父類引用類型屬性被共享的問題。
優點:避免了引用類型屬性被共享的問題,同時可以向父類構造函數傳遞參數。
缺點:每次都需要調用父類構造函數,無法復用父類原型對象上的方法,導致內存浪費,並且子類實例無法訪問父類原型上的屬性和方法。
三、組合繼承(原型鏈繼承和經典繼承的組合)
組合繼承是將原型鏈繼承和借用構造函數繼承結合使用的方式。通過借用構造函數繼承父類的實例屬性,通過原型鏈繼承父類的原型屬性和方法,從而實現繼承。
代碼示例:
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function () {
console.log(this.name);
}
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child = new Child("child", 18);
child.getName(); // "child"
實現原理:通過在子類構造函數內部通過 call 或 apply 方法調用父類構造函數,從而實現繼承父類實例屬性。然後將子類原型指向父類的實例,從而實現繼承父類原型屬性及方法。
優點:既繼承了父類構造函數屬性,又繼承了父類原型上的屬性及方法。
缺點:會調用兩次父類構造函數,造成內存浪費。
四、原型式繼承
原型式繼承通過利用一個空對象作為中介實現對對象的複製,從而實現繼承。
代碼示例:
const parent = {
name: "parent",
getName: function () {
console.log(this.name);
}
};
const child = Object.create(parent);
child.name = "child";
child.getName(); // "child"
實現原理:通過 Object.create() 方法以一個對象作為參數,創建一個繼承自該對象的新對象。
優點:可以實現對某個對象進行簡單繼承,避免了構造函數和原型的複雜度。
缺點:父類引用類型屬性共享給所有子類實例,容易造成意外修改,無法向父類構造函數傳遞參數。
五、寄生式繼承
寄生式繼承是在原型式繼承的基礎上進行了封裝,利用一個函數返回一個以父類對象為基礎的新對象,實現繼承。
代碼示例:
const parent = {
name: "parent",
getName: function () {
console.log(this.name);
}
};
function createChild(parent, name) {
const child = Object.create(parent);
child.name = name;
return child;
}
const child = createChild(parent, "child");
child.getName(); // "child"
實現原理:藉助工廠模式的思想,通過一個函數返回一個對象,從而實現繼承。
優點:在不需要耦合構造函數的情況下實現繼承。
缺點:與構造函數、原型鏈繼承等方式一樣,父類引用類型屬性共享給所有子類實例,容易造成意外修改,無法向父類構造函數傳遞參數。
六、寄生組合式繼承(最優解)
寄生組合式繼承是在組合繼承的基礎上進行改良,通過寄生式繼承來繼承父類的原型對象,從而避免了組合繼承中調用兩次父類構造函數的問題。
代碼示例:
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function () {
console.log(this.name);
}
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var child = new Child("child", 18);
child.getName(); // "child"
實現原理:通過 Object.create() 方法以父類原型對象作為參數,創建一個繼承自該對象的新對象,從而避免了調用兩次父類構造函數的問題。
優點:避免了調用兩次父類構造函數的問題,既繼承了父類構造函數屬性,又繼承了父類原型上的屬性及方法。
缺點:代碼複雜度較高。
原創文章,作者:UNWVL,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/334469.html