繼承

原型鏈的2個重要點

  1. __proto__ === constructor.prototype 砂心;
  2. 對象查找一個屬性的時候,會首先檢查自身是否有這個屬性夺欲,如果沒有谓罗,則沿著原型鏈(也就是 __proto__ )往上尋找,直到尋找到 null 顶别。

繼承

繼承是為了復用對象谷徙。下面是幾種繼承方法:

  1. 原型鏈繼承

    function A(name) {
        this.name = name;
        this.city = ['Guangzhou', 'Shenzhen'];
    };
    A.prototype.getName = function () {
        return this.name
    };
    function B(sex) {
        this.sex = sex;
    }
    B.prototype = new A('Bobo');
    var c = new B('male');
    c.getName(); // Bobo
    // 缺陷
    c.city.push('Shanghai');
    var d = new B('jojo');
    d.city; // [ 'Guangzhou', 'Shenzhen', 'Shanghai' ]
    

    解釋:

    根據(jù) __proto__ === constructor.prototype 可以知道,子類實例(也就是c)可以通過 __proto__ 訪問到子類(也就是B)的 prototype 驯绎,由于 B.prototype = new A('Bobo') , 子類的實例能訪問到父類(也就是A)的實例完慧。這樣,子類實例(c)就能訪問到父類的私有方法剩失,然后通過父類實例(也就是 new A('Bobo') 或者 B.prototype 或者 c.__proto__)的 __proto__ (也就是 new A('bobo').__ptoto__ 或者 B.prototype.__proto__ 或者 c.__proto__.__proto__ ) 訪問到父類的原型上的方法屈尼。

    子類繼承父類的屬性和方法是將父類的私有屬性和公有方法都作為自己的公有屬性的方法册着。如果私有屬性是引用類型的,實例進行修改脾歧,將會導致下一個實例的對應的私有屬性發(fā)生變化甲捏。

    優(yōu)勢:可以函數(shù)共享。

    缺陷:當上一個實例修改了原型中的 引用類型 的值鞭执,會影響到下一個實例摊鸡。

  2. 構造函數(shù)繼承

    function A (name) {
        this.city = ['Guangzhou', 'Shenzhen'];
        this.name = name;
    }
    A.prototype.getName = function() {
        return this.name;
    };
    function B(name, sex) {
        A.call(this, name);
        this.sex = sex;
    }
    var c = new B('coco', 'male');
    // c.getName(); // 無法共享方法
    c.name; // coco
    c.sex; // male
    c.city.push('Shanghai');
    var d = new B('jojo', 'female');
    d.city; // [ 'Guangzhou', 'Shenzhen' ]
    

    解釋:

    為什么叫構造函數(shù)繼承呢,是因為對于新new對象(比如例子的c)來說蚕冬,B就是他的構造函數(shù)免猾,在B內進行繼承,所以叫構造函數(shù)繼承囤热。

    構造函數(shù)繼承猎提,就是在子類函數(shù)里面使用 call, apply 來改變 this 指向,讓它指向父類旁蔼,改變上下文環(huán)境锨苏。由于父類方法是掛載在 prototype 所以子類無法獲取到掛載的方法。

    優(yōu)勢:屬性是實例借助構造函數(shù)自己生成的棺聊,所以各個實例的屬性是各自獨立的伞租。創(chuàng)建子類實例的時候,可以向父類傳遞參數(shù)限佩,可以實現(xiàn)多重繼承(call多個對象)

    缺陷:實例是子類實例葵诈,不是父類的實例;無法繼承父類原型的屬性和方法祟同;不能復用作喘,因為每個子類都有父類實例函數(shù)的副本。

  3. 結合繼承

    function A (name) {
      this.city = ['Guangzhou', 'Shenzhen'];
      this.name = name;
    }
    A.prototype.getName = function() {
      return this.name;
    };
    function B(name, sex) {
      A.call(this, name); // 調用了一次父類的構造函數(shù)晕城,會被下次調用屏蔽
      this.sex = sex;
    }
    B.prototype = new A(); // 又調用了一次父類的構造函數(shù)泞坦, A原型上的屬性其實是沒有必要的
    // 可以用 B.prototype = A.prototype來避免2次調用父類構造函數(shù),
    // 但是這樣砖顷,造成了子類原型鏈上的混亂贰锁,無法知道實例是子類創(chuàng)造的還是父類創(chuàng)造的,它們指向同一個
    // 可以用 Object.create(A.prototype)
    // B.prototype.constructor = B滤蝠;來替代豌熄,不過這種方法可以參照圣杯模式
    var c = new B('dodo', 'male');
    c.getName(); // dodo
    c.city.push('Shanghai');
    var d = new B('eoeo', 'female');
    d.city; // [ 'Guangzhou', 'Shenzhen' ]
    

    顯而易見地,結合繼承結合了原型繼承和構造函數(shù)繼承的優(yōu)點几睛。

    缺陷:子類原型上有一份多余的父類實例屬性房轿,父類構造函數(shù)被調用了2次,生成了2份,子類實例上的那一份屏蔽了子類原型上的囱持。

  4. 寄生結合繼承(圣杯模式)

    // 寫法1
    function inherit(c, p) {
      function f() {}
      f.prototype = p.prototype;
      c.prototype = new f();
      c.prototype.constructor = c;
      // uber是超類夯接,儲存這個目標是繼承于誰,可寫可不寫
      c.prototype.uber = p.prototype;
    }
    
    // 寫法2
    var inherit2 = (function(c, p){
      var F = function(){};
      return function(c, p) {
        F.prototype = p.prototype;
        c.prototype = new F();
        c.uber = p.prototype;
        c.prototype.constructor = c;
      }
    })();
    
    function A (name) {
      this.city = ['Guangzhou', 'Shenzhen'];
      this.name = name;
    }
    A.prototype.getName = function() {
      return this.name;
    };
    function B(name, sex) {
      this.sex = sex;
      this.name = name;
    }
    
    inheirt(B, A);
    var c = new B('fofo', 'male');
    c.name; // fofo
    c.sex; // male
    // c.city; // 沒有這個屬性
    c.getName(); // fofo
    

    創(chuàng)建一個中間對象f纷妆,將父類的 prototype 指向中間對象f的 prototype ;然后子類實現(xiàn)f的原型繼承盔几,再矯正子類的constructor ,這樣不會造成原型鏈的混亂掩幢。從而隔開了子類修改原型對父類造成的影響逊拍。但是無法繼承父類的屬性(比如父類的city屬性);

    關鍵點在于 __proto__===constructor.prototype 的理解际邻。對象會循著 __proto__ 向上尋找屬性芯丧,如果自身沒有的話。這樣當 A.prototype = new B() 的時候世曾,var c = new A()c 執(zhí)行一個方法或者查找一個屬性沒有找到的時候缨恒,c.__proto__ -> A.prototype(new B()) -> A.prototype.__proto__ -> B.prototype -> ... -> null ; 所以這樣是可以實現(xiàn)原型鏈查找,這也是繼承的體現(xiàn)之處轮听。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末骗露,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子血巍,更是在濱河造成了極大的恐慌萧锉,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件述寡,死亡現(xiàn)場離奇詭異柿隙,居然都是意外死亡,警方通過查閱死者的電腦和手機辨赐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門优俘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掀序,你說我怎么就攤上這事〔研觯” “怎么了不恭?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長财饥。 經(jīng)常有香客問我换吧,道長,這世上最難降的妖魔是什么钥星? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任沾瓦,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘贯莺。我一直安慰自己风喇,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布缕探。 她就那樣靜靜地躺著魂莫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爹耗。 梳的紋絲不亂的頭發(fā)上耙考,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音潭兽,去河邊找鬼倦始。 笑死,一個胖子當著我的面吹牛山卦,可吹牛的內容都是我干的楣号。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怒坯,長吁一口氣:“原來是場噩夢啊……” “哼炫狱!你這毒婦竟也來了?” 一聲冷哼從身側響起剔猿,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤视译,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后归敬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酷含,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年汪茧,在試婚紗的時候發(fā)現(xiàn)自己被綠了椅亚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡舱污,死狀恐怖呀舔,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情扩灯,我是刑警寧澤媚赖,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站珠插,受9級特大地震影響惧磺,放射性物質發(fā)生泄漏。R本人自食惡果不足惜捻撑,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一磨隘、第九天 我趴在偏房一處隱蔽的房頂上張望缤底。 院中可真熱鬧,春花似錦番捂、人聲如沸个唧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坑鱼。三九已至,卻和暖如春絮缅,著一層夾襖步出監(jiān)牢的瞬間鲁沥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工耕魄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留画恰,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓吸奴,卻偏偏與公主長得像允扇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子则奥,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內容

  • 轉自:360圖書館 時間:2016-9-26 原標題:使用Javascript读处,可以實現(xiàn)多層繼承 1.javasc...
    Michael_林閱讀 5,761評論 0 4
  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,332評論 0 10
  • 繼承有什么作用? (難度:3*) 繼承可以使一個對象直接使用另一個對象的屬性和方法糊治。 有幾種常見創(chuàng)建對象的方式? ...
    coolheadedY閱讀 527評論 0 0
  • 繼承的概念:子類可以使用父類共享的屬性和方法,避免重復代碼提高代碼復用性罚舱。 原型鏈:子類可以共享父類的實例對象和實...
    淺秋_6672閱讀 400評論 0 0
  • 1. apply井辜、call 、bind有什么作用管闷,什么區(qū)別粥脚? call ,apply的作用:調用一個函數(shù),傳入函數(shù)...
    Rising_suns閱讀 395評論 0 0