四周搞定《JavaScript 高級程序設(shè)計(jì)》 - 讀書筆記(Day 09)

繼承

在 ECMAScript 中由于函數(shù)沒有簽名卫漫,只支持實(shí)現(xiàn)繼承柑爸,依靠原型鏈來實(shí)現(xiàn)沛慢。

1.原型鏈

基本思想:利用原型讓一個引用類型繼承另一個引用類型的屬性和方法服球。

function SuperType() {
  this.property = true;
}

SuperType.prototype.getSuperValue = function() {
  return this.property;
}

function SubType() {
  this.subproperty = false;
}

// 繼承了 SuperType  設(shè)置原型為超類的實(shí)例
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function() {
  return this.subproperty;
}

var instance = new SubType();
// 調(diào)用到超類的方法
alert(instance.getSuperValue()); // true

以上的來個類型都分別有一個屬性和方法, SubType 繼承是通過創(chuàng)建 SuperType 的實(shí)例颠焦,將該實(shí)例賦給 SubType.prototype 實(shí)現(xiàn)斩熊,本質(zhì)是重寫原型對象。

1.1 別忘記默認(rèn)的原型

所有的引用類型默認(rèn)都繼承了 Object伐庭,這個繼承也是通過原型鏈實(shí)現(xiàn)粉渠。所有函數(shù)的默認(rèn)原型都是 Object 的實(shí)例,因此默認(rèn)原型都會包含一個內(nèi)部指針([[prototype]]__proto__) 指向 Object.prototype圾另。

1.2 確定原型和實(shí)例的關(guān)系

  • 使用 instanceof 操作符霸株,測試實(shí)例與原型鏈中出現(xiàn)過的構(gòu)造函數(shù),結(jié)果會返回 true集乔。
instance instanceof Object; // true
instance instanceof SuperType; // true
instance instanceof SubType; // true
  • 使用 isPrototypeOf() 方法去件,只要是原型鏈中出現(xiàn)過的原型,也會返回 true扰路。
Object.prototype.isPrototypeOf(instance); // true
SuperType.prototype.isPrototypeOf(instance); // true
SubType.prototype.isPrototypeOf(instance); // true

1.3 謹(jǐn)慎地定義方法

給原型添加方法的代碼須放在替換原型的語句之后(否則方法是在默認(rèn)的原型上尤溜,替換后的原型是超類的實(shí)例)。

function SuperType() {
  this.property = true;
}

SuperType.prototype.getSuperValue = function() {
  return this.property;
}

function SubType() {
  this.subproperty = false;
}

// 繼承了 SuperType  替換原型實(shí)例
SubType.prototype = new SuperType();

// 添加了新方法(后置)
SubType.prototype.getSubValue = function() {
  return this.subproperty;
}

// 重寫超類型中的方法(后置)
SubType.prototype.getSuperValue = function() {
  return this.false;
}

var instance = new SubType();
// 調(diào)用到超類的方法
alert(instance.getSuperValue()); // true

1.4 原型鏈的問題

包含引用類型值的原型屬性會被所有實(shí)例共享汗唱,因此需要在構(gòu)造函數(shù)而不是原型對象中定義屬性宫莱。

2. 借用構(gòu)造函數(shù)

在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù),同時通過使用 apply()call() 方法也可以在(將來)新創(chuàng)建的對象上執(zhí)行構(gòu)造函數(shù)哩罪。

function SuperType() {
  this.colors = ["red", "blue", "green"];
}

function SubType() {
  // 繼承了 SuperType
  SuperType.call(this);
}

var ins1 = new SubType();
ins1.colors.push("black");
alert(ins1.colors); // "red, blue, green, black"

var ins2 = new SubType();
alert(ins2.colors); // "red, blue, green"

2.1 傳遞參數(shù)

借用構(gòu)造函數(shù)可以在子類型構(gòu)造函數(shù)中向超類型構(gòu)造函數(shù)傳遞參數(shù)授霸。

function SuperType(name) {
  this.name = name;
}

function SubType() {
  // 繼承了 SuperType,同時傳遞了參數(shù)
  SuperType.call(this, "Nicklas");

  // 實(shí)例屬性
  this.age = 29;
}

var ins = new SubType();
alert(ins.name); // "Nicklas"
alert(ins.age); // 29

2.2 借用構(gòu)造函數(shù)的問題

僅借用構(gòu)造函數(shù)际插,無法避免構(gòu)造函數(shù)模式的問題碘耳,即方法都在構(gòu)造函數(shù)中定義,無法實(shí)現(xiàn)復(fù)用函數(shù)框弛,同時辛辨,在超類型原型中定義的方法,對子類型也是不可見的功咒,因此構(gòu)造函數(shù)技術(shù)很少單獨(dú)使用愉阎。

3. 組合繼承

將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一塊绞蹦,思路是使用原型鏈實(shí)現(xiàn)對原型屬性和方法的繼承力奋,而通過借用構(gòu)造函數(shù)來實(shí)現(xiàn)對實(shí)例屬性的繼承,一方面通過原型上定義方法實(shí)現(xiàn)函數(shù)復(fù)用幽七,又能保證每個實(shí)例都有自己的屬性景殷。

function SuperType(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function() {
  alert(this.name);
}

function SubType(name, age) {
  // 繼承屬性
  SuperType.call(this, name);
  this.age = age;
}

// 繼承方法
SubType.prototype = new SuperType();

SubType.prototype.sayAge = function() {
  alert(this.age)
}

var ins1 = new SubType("Nicklas", 29);
ins1.colors.push("black");
alert(ins1.colors); // "red, blue, green, black"
ins1.sayName(); // "Nicklas"
ins1.sayAge(); // 29

var ins2 = new SubType("Greg", 27);
alert(ins2.colors); // "red, blue, green"
ins2.sayName(); // "Greg"
ins2.sayAge(); // 27

4. 原型式繼承

借助原型可以基于已有的對象創(chuàng)建新對象,同時還不必因此創(chuàng)建自定義類型。

function object(o) {
  function F() { }
  F.prototype = o;
  return new F();
}

object() 函數(shù)內(nèi)部猿挚,先創(chuàng)建一個臨時性的構(gòu)造函數(shù)咐旧,然后將傳入的對象作為這個構(gòu)造函數(shù)的原型,最后返回了這個臨時類型的一個新實(shí)例绩蜻。

5. 寄生式繼承

寄生式繼承的思路與寄生構(gòu)造函數(shù)和工廠模式類似铣墨,即創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強(qiáng)對象办绝,最后再像真的是做了所有工作一樣返回對象伊约。

function createAnother(ori) {
  var clone = object(ori); // 通過調(diào)用函數(shù)創(chuàng)建一個新對象
  clone.sayHi = function() { // 以某種方式來增強(qiáng)這個對象
    alert("hi");
  };
  retrun clone;
}

6. 寄生組合式繼承

組合繼承最大的問題是任何時候都會兩次調(diào)用超類型構(gòu)造函數(shù):一次是在創(chuàng)建子類原型的時候,一次是在子類型構(gòu)造函數(shù)內(nèi)部孕蝉。

寄生組合式繼承即通過借用構(gòu)造函數(shù)來繼承屬性屡律,通過原型鏈的混成形式來繼承方法。不必為了制定子類型的原型而調(diào)用超類型的構(gòu)造函數(shù)降淮,因?yàn)槲覀兯枰臒o非就是超類型原型的一個副本而已。本質(zhì)上,就是使用寄生式繼承來繼承超類型的原型糊余,然后再將結(jié)果指定給子類型的原型棚赔。

function inheritPrototype(subType, superType) {
  var protptype = object(superType.prototype); // 創(chuàng)建對象
  prototype.constructor = subType; // 增強(qiáng)對象
  subType.prototype = prototype; // 指定對象
}

后記

至此,第六章算是結(jié)束了系吩,但是整個過程有點(diǎn)痛苦繁成,因?yàn)閺睦斫鈱用鎭碇v,這一章的篇幅還是蠻大的淑玫,而且本書中這一章寫得太學(xué)術(shù)了巾腕,寫筆記也是挺累的,而且自認(rèn)為這三節(jié)筆記寫得質(zhì)量有點(diǎn)低絮蒿,但是一直跑不出這章太影響效率了尊搬,計(jì)劃在本書筆記完結(jié)后再來做一些簡略的補(bǔ)充和完善。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末土涝,一起剝皮案震驚了整個濱河市佛寿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌但壮,老刑警劉巖冀泻,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蜡饵,居然都是意外死亡弹渔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進(jìn)店門溯祸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肢专,“玉大人舞肆,你說我怎么就攤上這事〔┱龋” “怎么了椿胯?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長剃根。 經(jīng)常有香客問我哩盲,道長,這世上最難降的妖魔是什么狈醉? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任种冬,我火速辦了婚禮,結(jié)果婚禮上舔糖,老公的妹妹穿的比我還像新娘娱两。我一直安慰自己,他們只是感情好金吗,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布十兢。 她就那樣靜靜地躺著,像睡著了一般摇庙。 火紅的嫁衣襯著肌膚如雪旱物。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天卫袒,我揣著相機(jī)與錄音宵呛,去河邊找鬼。 笑死夕凝,一個胖子當(dāng)著我的面吹牛宝穗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播码秉,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼逮矛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了转砖?” 一聲冷哼從身側(cè)響起须鼎,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎府蔗,沒想到半個月后晋控,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姓赤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年赡译,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片模捂。...
    茶點(diǎn)故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡捶朵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出狂男,到底是詐尸還是另有隱情综看,我是刑警寧澤,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布岖食,位于F島的核電站红碑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏泡垃。R本人自食惡果不足惜析珊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔑穴。 院中可真熱鬧忠寻,春花似錦、人聲如沸存和。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捐腿。三九已至纵朋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茄袖,已是汗流浹背操软。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宪祥,地道東北人聂薪。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像蝗羊,于是被迫代替她去往敵國和親胆建。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評論 2 361

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