JavaScript 原型鏈主要有以下幾種方式來查找和繼承屬性和方法:
通過將子類的原型對象(prototype)設(shè)置為父類的一個實例,從而實現(xiàn)繼承。這種方式的優(yōu)點是簡單易懂,但缺點是所有子類實例共享父類的引用屬性,無法實現(xiàn)多繼承。
function Parent() {
this.name = 'parent';
}
Parent.prototype.getName = function() {
return this.name;
};
function Child() {
this.age = 18;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child();
console.log(child1.getName()); // 'parent'
在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù),并將子類實例作為上下文(this)。這種方式的優(yōu)點是可以避免子類實例共享父類引用屬性的問題,但缺點是無法繼承父類原型上的方法。
function Parent() {
this.name = 'parent';
}
Parent.prototype.getName = function() {
return this.name;
};
function Child() {
Parent.call(this);
this.age = 18;
}
var child1 = new Child();
console.log(child1.name); // 'parent'
console.log(child1.getName); // undefined
結(jié)合原型鏈繼承和構(gòu)造函數(shù)繼承的優(yōu)點,實現(xiàn)屬性和方法的繼承。缺點是父類構(gòu)造函數(shù)會被調(diào)用兩次。
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function() {
return this.name;
};
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child('parent', 18);
console.log(child1.name); // 'parent'
console.log(child1.getName()); // 'parent'
通過創(chuàng)建一個新對象并將其原型設(shè)置為父類實例,實現(xiàn)繼承。這種方式的缺點是同樣會導致子類實例共享父類引用屬性。
function Parent() {
this.name = 'parent';
}
Parent.prototype.getName = function() {
return this.name;
};
function createObject(proto) {
function F() {}
F.prototype = proto;
return new F();
}
var child1 = createObject(Parent.prototype);
child1.name = 'child';
console.log(child1.getName()); // 'child'
在原型式繼承的基礎(chǔ)上,增加一個函數(shù)用于封裝繼承過程并添加新的方法。這種方式的缺點仍然是子類實例共享父類引用屬性。
function Parent() {
this.name = 'parent';
}
Parent.prototype.getName = function() {
return this.name;
};
function createChild() {
var clone = Object.create(Parent.prototype);
clone.age = 18;
return clone;
}
var child1 = createChild();
child1.name = 'child';
console.log(child1.getName()); // 'child'
結(jié)合寄生式繼承和組合繼承的優(yōu)點,避免了父類構(gòu)造函數(shù)被調(diào)用兩次的問題。
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function() {
return this.name;
};
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var child1 = new Child('parent', 18);
console.log(child1.name); // 'parent'
console.log(child1.getName()); // 'parent'