之前提到了JS中比較簡單的設計模式,在各種設計模式中被最常使用的工具之一就是原型鏈的繼承。作為OOP的特質之一——繼承,今天主要談談JS中比較簡單的繼承方法。 最基礎的原型鏈繼承在這裡就不覆述了,主要講一下其他的繼承模式。1.借用構造函數繼承function Father (name) {...
之前提到了JS中比較簡單的設計模式,在各種設計模式中被最常使用的工具之一就是原型鏈的繼承。作為OOP的特質之一——繼承,今天主要談談JS中比較簡單的繼承方法。
最基礎的原型鏈繼承在這裡就不覆述了,主要講一下其他的繼承模式。
1.借用構造函數繼承
function Father (name) { this.name=name; } function Son (name) { Father.call(this,name); //在子類型中調用超類型的構造函數 this.age=15; } var me=new Son("Su");
好處:可以為子類型傳遞參數,如圖中的name屬性。
壞處:1.方法在構造函數中定義,無法復用。2.超類型原型中定義的方法對子類型是不可見的。
2.組合繼承(綜合原型鏈與構造函數)
//超類型構造函數
function Father (name) { this.name=name; this.famMember=[]; }
//超類型構造函數原型方法 Father.prototype.sayName=function () { alert(this.name); }
//子類型構造函數 function Son (name,age) { Father.call(this,name); //構造函數方法 this.age=age; } Son.prototype=new Father(); //重寫子類型原型對象 Son.prototype.constructor=Son; //重寫構造函數屬性指向子類型 Son.prototype.sayAge=function () { alert(this.age); } //重寫原型對象後再加入方法 var me=new Son("Su",15); me.famMember.push("dad","mom"); //子類型可以調用超類型構造函數內的方法
var he=new Son("Li",14);
alert(he.famMember); // []
好處:不同的子類既可以擁有自己的屬性,也可以使用相同的方法。
壞處:這種方法需要調用2次超類型的構造函數,同名的屬性方法會被覆蓋一次。
3.原型式繼承 (類似Object.create())
function object (o) { function F () {} F.prototype=o; return new F(); }
var obj={}; //將obj對象傳入作為新對象的原型。
var me=object(obj);
使用這種方法繼承需要有一個對象作為原型對象,所以所有繼承其的子類型的屬性方法都是共用的。
ES5通過新增Object.creatr()方法規範了原型式繼承。
4.寄生式繼承 (可以設置私有方法的原型式繼承)
function object (o) { function F () {} F.prototype=o; return new F(); } var obj={}; //將obj對象傳入作為新對象的原型。到這裡都與原型式繼承相同
function creObj(o) {
var clone=object(obj);
clone.sayHi=function () {
alert("Hi");
};
return clone;
} var me=creObj(obj);
好處:這種方式彌補了原型式繼承只有公有屬性方法的缺陷,使子類型能有私有屬性方法。
5.寄生組合式繼承
function inherit (father,son) { var pro=Object(father.prototype); //創建超類型原型對象的副本 pro.constructor=son; son.prototype=pro; //將副本作為子類型的原型對象 }
本方法用於彌補組合繼承中屬性方法覆蓋的問題。
用上圖代碼代替組合繼承中 Son.prototype=new Father(); 這段代碼。這樣只需調用一次父類型的構造函數,避免了創造多餘不必要的屬性方法,並且保持了原型鏈不改變,是一種理想的引用類型繼承方法。