一绸栅、原型的繼承
只需要將子級的原型對象設(shè)置為父級的一個(gè)實(shí)例,加入到原型鏈中即可。
// 繼承原型
cPerson.prototype = new Person(name, age);
// 添加更多方法
cPerson.prototype.getLive = function() {}
缺點(diǎn):
1.來自原型對象的引用屬性是所有實(shí)例共享的哟玷,原型中的一改則全改
2.創(chuàng)建子類實(shí)例時(shí),無法向父類構(gòu)造函數(shù)傳參
二一也、構(gòu)造函數(shù)的繼承
等于是把父類的實(shí)例屬性復(fù)制了一份給子類實(shí)例裝上了(完全沒有用到原型)
(構(gòu)造函數(shù)的本質(zhì)巢寡,它其實(shí)是在new內(nèi)部實(shí)現(xiàn)的一個(gè)復(fù)制過程)
在繼承時(shí)想要的,就是想父級構(gòu)造函數(shù)中的操作在子級的構(gòu)造函數(shù)中重現(xiàn)一遍即可椰苟。我們可以通過call方法來達(dá)到目的抑月。
// 構(gòu)造函數(shù)的繼承function cPerson(name, age, job) {
Person.call(this, name, age);
this.job = job;
}
缺點(diǎn):
無法實(shí)現(xiàn)函數(shù)復(fù)用,每個(gè)子類實(shí)例都持有一個(gè)新的fun函數(shù)舆蝴,太多了就會(huì)影響性能谦絮,內(nèi)存爆炸。
三洁仗、組合繼承(最常用)
把實(shí)例函數(shù)都放在原型對象上层皱,以實(shí)現(xiàn)函數(shù)復(fù)用。同時(shí)還要保留借用構(gòu)造函數(shù)方式的優(yōu)點(diǎn)赠潦,通過Super.call(this);繼承父類的基本屬性和引用屬性并保留能傳參的優(yōu)點(diǎn)叫胖;通過Sub.prototype = new Super();繼承父類函數(shù),實(shí)現(xiàn)函數(shù)復(fù)用
function Sub(){
Super.call(this); // 核心
// ...
}
Sub.prototype = new Super(); // 核心
缺點(diǎn): 由于調(diào)用了2次父類的構(gòu)造方法她奥,會(huì)存在一份多余的父類實(shí)例屬性(原因: 第一次SuperType.call(this);語句從父類拷貝了一份父類實(shí)例屬性給子類作為子類的實(shí)例屬性瓮增,第二次SubType.prototype = new SuperType();創(chuàng)建父類實(shí)例作為子類原型疲陕,此時(shí)這個(gè)父類實(shí)例就又有了一份實(shí)例屬性,但這份會(huì)被第一次拷貝來的實(shí)例屬性屏蔽掉钉赁,所以多余蹄殃。)
四、寄生組合繼承(最佳方式)
( 對組合繼承的優(yōu)化)
用beget(Super.prototype);切掉了原型對象上多余的那份父類實(shí)例屬性
function beget(obj){ // 生孩子函數(shù) beget:龍beget龍你踩,鳳beget鳳诅岩。
var F = function(){};
F.prototype = obj;
return new F(); //返回一個(gè)新的構(gòu)造函數(shù)F的實(shí)例
}
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);
五、原型式
用生孩子函數(shù)得到得到一個(gè)“純潔”的新對象(“純潔”是因?yàn)闆]有實(shí)例屬性)带膜,再逐步增強(qiáng)之(填充實(shí)例屬性)
(beget函數(shù)的參數(shù)為父類的一個(gè)實(shí)例化對象吩谦,這個(gè)參數(shù)作為新構(gòu)造函數(shù)的原型)
function beget(obj){ // 生孩子函數(shù) beget:龍beget龍,鳳beget鳳膝藕。
var F = function(){};
F.prototype = obj;
return new F();
}
function Super(){
this.val = 1;
this.arr = [1];
}
// 拿到父類對象
var sup = new Super();
// 生孩子
var sub = beget(sup); // 核心
// 增強(qiáng)
sub.attr1 = 1;
sub.attr2 = 2;
//sub.attr3...
六式廷、寄生式
給原型式繼承穿了個(gè)馬甲而已,看起來更像繼承了(上面介紹的原型式繼承更像是對象復(fù)制)
注意:beget函數(shù)并不是必須的芭挽,換言之滑废,創(chuàng)建新對象 -> 增強(qiáng) -> 返回該對象,
這樣的過程叫寄生式繼承袜爪,新對象是如何創(chuàng)建的并不重要(用beget生的蠕趁,new出來的,字面量現(xiàn)做的辛馆。俺陋。都可以)
(beget函數(shù)的參數(shù)為父類的一個(gè)實(shí)例化對象,這個(gè)參數(shù)作為新構(gòu)造函數(shù)的原型)
缺點(diǎn):無法實(shí)現(xiàn)函數(shù)復(fù)用(沒用到原型昙篙,當(dāng)然不行)