上篇說了js的設計模式万栅,現在再說說繼承(不理解設計模式的可以看上篇)。
1伞辛、原型鏈
function Child(){
this.name= 'scater';
}
function Parent(){
this.age= 29;
}
//繼承了 SuperType
Child.prototype = new Parent();
Parent.prototype.getAge= function (){
return this.age;
};
const child1 = new Child();
console.log(child1.getAge()); //29
缺點:引用類型屬性被實例共享黍檩;創(chuàng)建子類實例時,無法向父類構造函數傳參始锚。
2刽酱、借用構造函數
function Child(){
this.name= 'scater';
Parent.call(this); // call和apply都可以
}
function Parent(){
this.age= 29;
this.getAge= function (){
return this.age;
}
};
const child1 = new Child();
console.log(child1.getAge()); //29
實例并不是父類的實例,只是子類的實例瞧捌;只能繼承父類的實例屬性和方法棵里,不能繼承原型屬性/方法;無法實現函數復用姐呐,每個子類都有父類實例函數的副本殿怜,影響性能
3、組合繼承
function Parent(){
this.age= 29;
this.getAge= function (){
return this.age;
}
};
function Child(){
this.name= 'scater';
Parent.call(this); // call和apply都可以
}
Child.prototype = new Parent();
Child.prototype.constructor = Child; // 將構造函數指向Child
Parent.prototype.getName = function (){
return this.name;
};
const child1 = new Child();
console.log(child1.getAge(), child1.getName ()); //29, 'scater'
可以繼承父級實例屬性/方法曙砂,也可以繼承父級原型屬性/方法头谜;但是調用了兩次父類構造函數,生成了兩份實例鸠澈。
4柱告、原型式繼承
function object(o){
function F(){}
F.prototype = o;
return new F();
}
var person = {
name: "scater",
friends: ["tom", "Lee"]
};
// 利用object繼承
const anotherPerson = object(person);
// 給子類添加自有屬性
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
console.log (anotherPerson.name, anotherPerson.friends); // Greg ["tom", "Lee", "Rob"]
ES5 通過新增 Object.create() 方法規(guī)范化了原型式繼承。這個方法接收兩個參數:一
個用作新對象原型的對象和(可選的)一個為新對象定義額外屬性的對象笑陈。
var anotherPerson = Object.create(person);
// 給子類添加自有屬性
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
console.log (anotherPerson.name, anotherPerson.friends); // Greg ["tom", "Lee", "Rob"]
在沒有必要創(chuàng)建構造函數际度,而只想讓一個對象與另一個對象保持類似的情況下,原型式
繼承是完全可以勝任的涵妥。但是包含引用類型值的屬性始終都會共享相應的值乖菱,就像使用原型模
式一樣。
5蓬网、寄生式繼承
function object(o){
function F(){}
F.prototype = o;
return new F();
}
function createAnother(original){
var clone = object(original); //通過調用函數創(chuàng)建一個新對象
clone.sayHi = function(){ //以某種方式來增強這個對象
console.log("hi");
};
return clone; //返回這個對象
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"
在主要考慮對象而不是自定義類型和構造函數的情況下窒所,寄生式繼承也是一種有用的模式。
6帆锋、寄生組合式繼承(推薦)
function Parent(){
this.age= 29;
}
function Child(name){
Parent.call(this);
this.name = name;
}
(function(){
// 創(chuàng)建一個沒有實例方法的類
var Super = function(){};
Super.prototype = Parent.prototype;
//將實例作為子類的原型
Child.prototype = new Super();
})();
Child.prototype.constructor = Child; // 將構造函數指向Child
const scater= new Child('scater');
console.log(scater.name, scater.age); // scater 29
7吵取、ES6 Class類的繼承
class Parent {
constructor() {
this.age = 29;
}
}
class Child extends Parent {
constructor(name) {
super(); // 在子類的構造函數中,只有調用super之后窟坐,才可以使用this關鍵字海渊,否則會報錯。
this.name = name;
}
}
const scater = new Child('scater');
console.log(scater.name, scater.age); // scater 29
ES6 的繼承機制哲鸳,實質是先將父類實例對象的屬性和方法臣疑,加到this上面(所以必須先調用super方法),然后再用子類的構造函數修改this徙菠。