三、構(gòu)造函數(shù)如何實現(xiàn)繼承
現(xiàn)在有一個”MED”對象的構(gòu)造函數(shù)(MED:Marketing Experience Design,營銷體驗設(shè)計) function MED(){ this.aim = "營銷體驗設(shè)計"; }
依然是”WD”對象的構(gòu)造函數(shù), function WD(skill,sex){ this.skill = skill; this.sex = sex; }
怎樣才能使”WD”繼承”MED”呢?
1. apply綁定構(gòu)造函數(shù)實現(xiàn)
最簡單的方法,大概就是使用call或apply方法,將父對象的構(gòu)造函數(shù)綁定在子對象上,也就是在子對象構(gòu)造函數(shù)中加一行:
function WD(skill,sex){
MED.apply(this, arguments);
this.skill = skill; this.sex = sex; }
var WD1 = new WD("Html","男"); console.log(WD1.aim); // "營銷體驗設(shè)計"
2. prototype模式實現(xiàn)
我們通常的做法是使用prototype屬性。如果”WD”的prototype對象,指向一個MED的實例,那么所有”WD”的實例,就能繼承MED了。 WD.prototype = new MED();//我們將WD的prototype對象指向一個MED的實例。 WD.prototype.constructor = WD; var WD1 = new WD("Html","男"); console.log(WD1.aim); // 營銷體驗設(shè)計
這句 WD.prototype = new MED();
相當(dāng)于完全刪除了prototype 對象原先的值,然后賦予一個新值。那么第二行又是什么意思呢? WD.prototype.constructor = WD;
原來,任何一個prototype對象都有一個constructor屬性,指向它的構(gòu)造函數(shù)。也就是說,WD.prototype 這個對象的constructor屬性,是指向WD的。 我們在前一步已經(jīng)刪除了這個prototype對象原來的值,所以新的prototype對象沒有constructor屬性,需要我們手動加上去,否則后面的”繼承鏈”會出問題。這就是第二行的意思。 注意,這是很重要的一點,編程時務(wù)必要遵守,下文都遵循這一點,即如果替換了prototype對象, o.prototype = {};
那么,下一步必然是為新的prototype對象加上constructor屬性,并將這個屬性指回原來的構(gòu)造函數(shù)。 o.prototype.constructor = o;
3. 從prototype直接繼承實現(xiàn)
由于MED對象中,不變的屬性都可以直接寫入MED.prototype。所以,我們也可以讓W(xué)D()跳過 MED(),直接繼承MED.prototype。 現(xiàn)在,我們先將MED對象改寫:
function MED(){ }
MED.prototype.skill = "MED";
然后,將WD的prototype對象指向MED的prototype對象,這樣就完成了繼承。
WD.prototype = MED.prototype; WD.prototype.constructor = WD;
var WD1 = new WD("Html","男");
console.log(WD1.skill); // MED
與前一種方法相比,這樣做的優(yōu)點是效率比較高(不用執(zhí)行和建立MED的實例了),比較省內(nèi)存。缺點是 WD.prototype和MED.prototype現(xiàn)在指向了同一個對象,那么任何對WD.prototype的修改,都會反映到MED.prototype。 所以,上面這一段代碼其實是有問題的。請看第二行 WD.prototype.constructor = WD;
這一句實際上把MED.prototype對象的constructor屬性也改掉了! console.log(MED.prototype.constructor); // WD
4. 利用一個空對象作為中介來實現(xiàn)
由于”直接繼承prototype”存在上述的缺點,所以可以利用一個空對象作為中介。
var F = function(){}; F.prototype = MED.prototype;
WD.prototype = new F(); WD.prototype.constructor = WD;
F是空對象,所以幾乎不占內(nèi)存。這時,修改WD的prototype對象,就不會影響到MED的prototype對象。 console.log(MED.prototype.constructor); // MED
5.利用 prototype模式的封裝函數(shù)
我們將上面的方法,封裝成一個函數(shù),便于使用。
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; }
使用的時候,方法如下 extend(WD,MED); var WD1 = new WD("Html","男"); console.log(WD1.aim); // 營銷體驗設(shè)計
這個extend函數(shù)就是YUI庫如何實現(xiàn)繼承的方法。
6. 拷貝繼承實現(xiàn)
上面是采用prototype方式來實現(xiàn)繼承。其實既然子對象會擁有父對象的屬性和方法,我們直接采用”拷貝”方法也可以達(dá)到效果。簡單說,如果把父對象的所有屬性和方法,拷貝進(jìn)子對象,不也能夠?qū)崿F(xiàn)繼承嗎? 首先,還是把MED的所有不變屬性,都放到它的prototype對象上。
function MED(){}
MED.prototype.aim = "營銷體驗設(shè)計";
然后,再寫一個函數(shù),實現(xiàn)屬性拷貝的目的。 function extendCopy(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } }
這個函數(shù)的作用,就是將父對象的prototype對象中的屬性,一一拷貝給Child對象的prototype對象。 使用的時候,這樣寫: extendCopy(WD, MED); var WD1 = new WD("Html","男"); console.log(WD1.aim); // 營銷體驗設(shè)計
出處:阿里媽媽UED
責(zé)任編輯:bluehearts
上一頁 重溫Javascript繼承機制 [2] 下一頁 重溫Javascript繼承機制 [4]
◎進(jìn)入論壇網(wǎng)頁制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評論。
|