JavaScript構(gòu)造函數(shù)的繼承

現(xiàn)在有一個"動物"對象的構(gòu)造函數(shù)掸鹅。

function Animal(){
    this.species = "動物";
}

還有一個"貓"對象的構(gòu)造函數(shù)。

function Cat(name,color){
    this.name = name;
    this.color = color;
}

怎樣才能使"貓"繼承"動物"呢亡鼠?

一旭从、 構(gòu)造函數(shù)綁定

使用call或apply方法稳强,將父對象的構(gòu)造函數(shù)綁定在子對象上,即在子對象構(gòu)造函數(shù)中加一行:

function Cat(name,color){
    Animal.apply(this, arguments);
    this.name = name;
    this.color = color;
}
var cat1 = new Cat("大毛","黃色");
alert(cat1.species);    // 動物

二和悦、 prototype模式

如果"貓"的prototype對象退疫,指向一個Animal的實例,那么所有"貓"的實例鸽素,就能繼承Animal了褒繁。

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黃色");
alert(cat1.species);    // 動物

上面,我們將Cat的prototype對象指向一個Animal的實例馍忽。

Cat.prototype = new Animal();

它相當(dāng)于完全刪除了prototype 對象原先的值,然后賦予一個新值。

Cat.prototype.constructor = Cat;

任何一個prototype對象都有一個constructor屬性絮爷,指向它的構(gòu)造函數(shù)壶硅。如果沒有"Cat.prototype = new Animal();"這一行,Cat.prototype.constructor是指向Cat的瓦呼;加了這一行以后喂窟,Cat.prototype.constructor指向Animal。

alert(Cat.prototype.constructor == Animal);    //true

另外央串,每個實例也有一個constructor屬性磨澡,默認調(diào)用prototype對象的constructor屬性。

alert(cat1.constructor == Cat.prototype.constructor);    // true

因此质和,在運行"Cat.prototype = new Animal();"這一行之后稳摄,cat1.constructor也指向Animal。

alert(cat1.constructor == Animal);    // true

這顯然會導(dǎo)致繼承鏈的紊亂(cat1明明是用構(gòu)造函數(shù)Cat生成的)饲宿,因此需要手動糾正厦酬,將Cat.prototype對象的constructor值改為Cat(即上面代碼第二行)。

如果替換了prototype對象瘫想,

o.prototype = {};

那么弃锐,下一步是為新的prototype對象加上constructor屬性,并將這個屬性指回原來的構(gòu)造函數(shù)殿托。

o.prototype.constructor = o;

三霹菊、 直接繼承prototype

由于Animal對象中,不變的屬性都可以直接寫入Animal.prototype支竹。所以旋廷,我們可以讓Cat()跳過 Animal(),直接繼承Animal.prototype礼搁。

先將Animal對象改寫:

function Animal(){ }
Animal.prototype.species = "動物";

然后饶碘,將Cat的prototype對象,指向Animal的prototype對象馒吴,這樣就完成了繼承扎运。

Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黃色");
alert(cat1.species);    // 動物

與前一種方法相比瑟曲,這樣做效率更高(不用執(zhí)行和建立Animal的實例),而且更省內(nèi)存豪治。但Cat.prototype和Animal.prototype現(xiàn)在指向了同一個對象洞拨,那么任何對Cat.prototype的修改,都會反映到Animal.prototype负拟。

所以烦衣,上面代碼第二行其實是有問題的:

Cat.prototype.constructor = Cat;

這里實際上把Animal.prototype對象的constructor屬性也改掉了!

alert(Animal.prototype.constructor);    // Cat

四掩浙、 利用空對象作為中介

由于"直接繼承prototype"存在上述的缺點花吟,所以就有第四種方法,利用一個空對象作為中介厨姚。

var F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;

F是空對象衅澈,所以幾乎不占內(nèi)存。這時谬墙,修改Cat的prototype對象矾麻,就不會影響到Animal的prototype對象。

alert(Animal.prototype.constructor);    // Animal

我們將上面的方法芭梯,封裝成一個函數(shù)险耀,便于使用。

function extend(Child, Parent) {
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber = Parent.prototype;
}

使用的時候玖喘,方法如下

extend(Cat,Animal);
var cat1 = new Cat("大毛","黃色");
alert(cat1.species);    // 動物

這個extend函數(shù)甩牺,就是YUI庫如何實現(xiàn)繼承的方法。

另外累奈,在函數(shù)體最后一行

Child.uber = Parent.prototype;

意思是為子對象設(shè)一個uber屬性贬派,這個屬性直接指向父對象的prototype屬性。這相當(dāng)于在子對象上打開一條通道澎媒,可直接調(diào)用父對象的方法搞乏。這一行放在這里,只是為了實現(xiàn)繼承的完備性戒努,純屬備用性質(zhì)请敦。

五、 拷貝繼承

如果把父對象的所有屬性和方法储玫,拷貝進子對象侍筛,也能夠?qū)崿F(xiàn)繼承。

首先撒穷,把Animal的所有不變屬性匣椰,都放到它的prototype對象上。

function Animal(){}
Animal.prototype.species = "動物";

然后端礼,再寫一個函數(shù)禽笑,實現(xiàn)屬性拷貝的目的入录。

function extend2(Child, Parent) {
    var p = Parent.prototype;
    var c = Child.prototype;
    for (var i in p) {
        c[i] = p[i];
    }
    c.uber = p;
}

這個函數(shù)的作用,就是將父對象的prototype對象中的屬性佳镜,全部拷貝給Child對象的prototype對象僚稿。

使用時這樣寫:

extend2(Cat, Animal);
var cat1 = new Cat("大毛","黃色");
alert(cat1.species);    // 動物

至于非構(gòu)造函數(shù)的繼承,請參考http://www.reibang.com/p/fde29e3f7116

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邀杏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子唬血,更是在濱河造成了極大的恐慌望蜡,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拷恨,死亡現(xiàn)場離奇詭異脖律,居然都是意外死亡,警方通過查閱死者的電腦和手機腕侄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門小泉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人冕杠,你說我怎么就攤上這事微姊。” “怎么了分预?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵兢交,是天一觀的道長。 經(jīng)常有香客問我笼痹,道長配喳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任凳干,我火速辦了婚禮晴裹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘救赐。我一直安慰自己涧团,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布经磅。 她就那樣靜靜地躺著少欺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪馋贤。 梳的紋絲不亂的頭發(fā)上赞别,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音配乓,去河邊找鬼仿滔。 笑死惠毁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的崎页。 我是一名探鬼主播鞠绰,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼飒焦!你這毒婦竟也來了蜈膨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤牺荠,失蹤者是張志新(化名)和其女友劉穎翁巍,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體休雌,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡灶壶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了杈曲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驰凛。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖担扑,靈堂內(nèi)的尸體忽然破棺而出恰响,到底是詐尸還是另有隱情,我是刑警寧澤涌献,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布渔隶,位于F島的核電站,受9級特大地震影響洁奈,放射性物質(zhì)發(fā)生泄漏间唉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一利术、第九天 我趴在偏房一處隱蔽的房頂上張望呈野。 院中可真熱鬧,春花似錦印叁、人聲如沸被冒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昨悼。三九已至,卻和暖如春跃洛,著一層夾襖步出監(jiān)牢的瞬間率触,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工汇竭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留葱蝗,地道東北人穴张。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像两曼,于是被迫代替她去往敵國和親皂甘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容