一.構造函數繼承
- 構造函數繼承的基本思路是在子類型的構造函數中,調用要繼承的構造函數,具體實現如下:
function Parent() {
this.name = ["heyushuo", "kebi"];
}
function Child() {
Parent.call(this);
// 或者 Parent.apply(this);
}
var Person1 = new Child();
Person1.name.push("kuli");
console.log(Person1.name); //["heyushuo", "kebi","kuli"];
var Person2 = new Child();
console.log(Person2.name); //["heyushuo", "kebi"];
// 通過上邊的兩個打印,Child的兩個實例繼承的name屬性不會互相影響
// 因為,創建Child實例的環境下調用Parent構造函數,這樣可以使得每個實例都會具有自己的name屬性,所以兩個不會互相影響
2. 優點(可以傳遞參數)
function Parent(name) {
this.name = name;
}
function Child() {
Parent.call(this, "heyushuo");
//或者Parent.apply(this, ["heyushuo"]);
}
var Person = new Child();
console.log(Person.name); //heyushuo
// 需要注意的:為了確保Parent構造函數不會重寫子類型的屬性,需要在Parent.call(this)之后在定義子類型中的屬性
3.構造函數的缺點
因為方法和屬性只能寫在構造函數中,因此不能實現函數復用 只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法 (原型中定義的方法和屬性對於子類是不可見的)
二.組合繼承(原型鏈和構造函數組合式繼承)
通俗來講就是用原型鏈實現對原型屬性和方法的繼承,用借用構造函數繼承來實現對實例屬性的繼承。
function Parent(name) {
this.name = name;
this.newArr = ["red", "blue", "green"];
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name) {
Parent.call(this, name);
this.age = 26;
}
Child.prototype = new Parent();
//重寫Child.prototype的constructor屬性,使其執行自己的構造函數Child
Child.prototype.constructor = Child;
Child.prototype.sayAge = function() {
console.log(this.age);
};
var Person1 = new Child("heyushuo");
console.log(Person1);
Person1.newArr.push("yellow");
console.log(Person.newArr); //["red", "blue", "green","yellow"]
Person.sayName(); //heyushuo
var Person2 = new Child("kebi");
console.log(Person2.newArr); //["red", "blue", "green"]
Person.sayName(); //kebi
通過一張圖來看一下:
總結
- 組合式繼承避免了原型鏈和構造函數的缺陷,融合了他們的有點,成為最常用的繼承模式
- 組合式繼承有一個缺點, 如上圖可以看出, 創建的實例和原型上存在兩份相同的屬性即(name 和 newArr);