1.簡單原型鏈
function Super(){
this.val = 1;
this.arr = [1];
}
function Sub(){
// ...
}
Sub.prototype = new Super(); // 核心
var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val); // 2
alert(sub2.val); // 1
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1, 2
優(yōu)點:簡單热押,易于實現(xiàn)
缺點:
- 修改sub1.arr后sub2.arr也變了西傀,因為來自原型對象的引用屬性是所有實例共享的。
可以這樣理解:執(zhí)行sub1.arr.push(2);先對sub1進(jìn)行屬性查找桶癣,找遍了實例屬性(在本例中沒有實例屬性)拥褂,沒找到,就開始順著原型鏈向上找牙寞,拿到了sub1的原型對象饺鹃,一搜身,發(fā)現(xiàn)有arr屬性间雀。于是給arr末尾插入了2悔详,所以sub2.arr也變了 - 創(chuàng)建子類實例時,無法向父類構(gòu)造函數(shù)傳參
2.借用構(gòu)造函數(shù)
function Super(val){
this.val = val;
this.arr = [1];
this.fun = function(){
// ...
}
}
function Sub(val){
Super.call(this, val); // 核心
// ...
}
var sub1 = new Sub(1);
var sub2 = new Sub(2);
sub1.arr.push(2);
alert(sub1.val); // 1
alert(sub2.val); // 2
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1
alert(sub1.fun === sub2.fun); // false
優(yōu)點:
解決了子類實例共享父類引用屬性的問題
創(chuàng)建子類實例時惹挟,可以向父類構(gòu)造函數(shù)傳參
缺點:
- 無法實現(xiàn)函數(shù)復(fù)用茄螃,每個子類實例都持有一個新的fun函數(shù),太多了就會影響性能匪煌,內(nèi)存爆炸责蝠。。
3.組合繼承(最常用)
function Super(){
// 只在此處聲明基本屬性和引用屬性
this.val = 1;
this.arr = [1];
}
// 在此處聲明函數(shù)
Super.prototype.fun = function(){};
function Sub(){
Super.call(this); // 核心
// ...
}
Sub.prototype = new Super(); // 核心
var sub1 = new Sub(1);
var sub2 = new Sub(2);
alert(sub1.fun === sub2.fun); // true
優(yōu)點:把實例函數(shù)都放在原型對象上萎庭,以實現(xiàn)函數(shù)復(fù)用霜医。同時還要保留借用構(gòu)造函數(shù)方式的優(yōu)點。
缺點:子類原型上有一份多余的父類實例屬性驳规,因為父類構(gòu)造函數(shù)被調(diào)用了兩次肴敛,生成了兩份,而子類實例上的那一份屏蔽了子類原型上的。
4.寄生組合繼承(最佳方式)
function beget(obj){
var F = function(){};
F.prototype = obj;
return new F();
}
function Super(){
// 只在此處聲明基本屬性和引用屬性
this.val = 1;
this.arr = [1];
}
// 在此處聲明函數(shù)
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
Super.call(this); // 核心
// ...
}
var proto = beget(Super.prototype); // 核心
proto.constructor = Sub; // 核心
Sub.prototype = proto; // 核心
var sub = new Sub();
alert(sub.val);
alert(sub.arr);
優(yōu)點:切掉了原型對象上多余的那份父類實例屬性医男。
缺點:出來寫起來麻煩一點砸狞,沒啥毛病镀梭!
5.原型式和6.寄生式就是寄生組合繼承的一種過度關(guān)系刀森,不詳細(xì)說明了。
具體詳解可見參考資料:
- JavaScript高級程序設(shè)計》
- JavaScript語言精粹
- Javascript 面向?qū)ο缶幊?阮一峰大神
- 重新理解JS的6種繼承方式