Javascript中的繼承

很多語言中都有繼承的概念往声,繼承這種東西為什么會出現?

簡而言之戳吝,繼承之所以出現浩销,就是為了減少重復無用功。
好比爸爸有10萬塊听哭,并且還有一項技能:用各種理財手段把10萬變成100萬慢洋,兒子們都想手里有錢并精通理財,那么只需要從爸爸那兒繼承錢和理財的方法欢唾,不用再自己苦哈哈得掙錢學理財了且警。

第一種:原型鏈繼承

原型鏈繼承非常的簡單粗暴,就是讓子類的prototype指向父類的一個實例礁遣,如下:

function Parent(name){
  this.name = name;
  this.friends = ['a','b','c','d'];
}
function Child() {
}
// 子類的原型是父類的一個實例
Child.prototype = new Parent('father');
let child1 = new Child();
let child2 = new Child();

console.log(child1.friends, child2.friends);  // [ 'a', 'b', 'c', 'd' ] [ 'a', 'b', 'c', 'd' ]

可以看到斑芜,孩子輕輕松松就認識了父親的朋友~
如果孩子把friends改掉會怎樣?

// child1.friends = ['a', 'b']; 
console.log(child1.friends, child2.friends); // [ 'a', 'b' ] [ 'a', 'b', 'c', 'd' ]

為什么 child1.friends = ['a', 'b']; 對 child2 沒有影響祟霍? 因為這種操作相當于給子類自己加了個自己的屬性而已杏头。

child1.friends.push('e');
console.log(child1.friends, child2.friends); // [ 'a', 'b' ] [ 'a', 'b', 'c', 'd' ]
[ 'a', 'b', 'c', 'd', 'e' ] [ 'a', 'b', 'c', 'd', 'e' ]

這樣寫結果就不一樣了盈包,因為這相當于修改了父親屬性,所有實例都會共享醇王。
這就是原型鏈繼承的一個缺點:一個變了其余都會變呢燥。
原型鏈的另一個缺點就是子類無法向父類構造函數傳遞參數,如果我想用new Children('name')就行不通了寓娩。

基于以上缺點叛氨,出現了借助構造函數的繼承方式。

第二種:借助構造函數的繼承

這種繼承方式其實是在子類的構造函數里調用父類的構造函數棘伴,如下:

function Parent(name){
   this.name = name;
   this.friends =  ['a','b','c'];
   this.sayName = function(){
      console.log('I am '+this.name);
   }
}
function Child(name){
   Parent.call(this, name);
}
const child1 = new Child('kid1'); //向父親構造函數傳參
const child2 = new Child('kid2');
console.log(child1, child2);
child1.sayName(); // 用到了父親的方法
child1.friends.push('d');
console.log(child2.friends);//  ['a','b','c'] 沒被受影響

借助構造函數寞埠,完美解決的以上兩個問題,但是仔細想想焊夸,sayName方法沒必要為每個實例都帶一個仁连,完全可以放在父類的prototype中。

第三種:組合繼承

其實這種方法就是將上面兩種結合起來阱穗,取長補短饭冬,相得益彰。把需要共享的方法揪阶,屬性用原型鏈繼承昌抠,不需要共享的就用構造函數。

function Parent(name){
   this.name = name;
   this.friends =  ['a','b','c'];
}
Parent.prototype.sayName = function(){
      console.log('I am '+this.name);
}
function Child(name){
   Parent.call(this, name);
}
Child.prototype = new Parent();

有時我只是僅僅想讓子類把父類的屬性復制粘貼到自己身上鲁僚,也要寫各種構造函數扰魂,各種原型鏈指向么?不需要蕴茴!

第四種:原型繼承

你只需要一行代碼:
const child = Object.create({name: 'parent', friends: ['a', 'b', 'c']});


image.png

那么Object.create方法做了什么?

function create(parent){
   let o = function(){};
   o.prototype = parent;
   return new o();
}

就是這么的簡單粗暴姐直!創(chuàng)建->原型指向->new一個返回去倦淀,一套步驟封裝好,用的時候就只要一行代碼就OK了声畏。

引申:

  1. Object.create() 和 new有什么不同撞叽?
    new的過程實際上是:
  • new一個空的Object
  • 讓this指向剛new出來的object
  • 完成構造函數里的賦值操作
  • 返回這個Object
    以上是我比較粗糙的理解,在網上搜索了一番之后插龄,發(fā)現我的理解還是有些偏差愿棋;
    首先,新建的空對象的[[prototype]]指向構造函數的prototype對象均牢;
    其次糠雨,綁定this實際上是通過constructor.call(obj)來實現的;
    學術一點兒的步驟:
  • 創(chuàng)建一個新的對象徘跪,這個對象的類型是object甘邀;
  • 設置這個新的對象的內部琅攘、可訪問性和[[prototype]]屬性為構造函數(指prototype.construtor所指向的構造函數)中設置的;
  • 執(zhí)行構造函數松邪,當this關鍵字被提及的時候坞琴,使用新創(chuàng)建的對象的屬性;
  • 返回新創(chuàng)建的對象(除非構造方法中返回的是‘無原型’)逗抑。
    可以得知剧辐,new 并不涉及“繼承”,只是單純的按模版(構造函數)創(chuàng)建對象邮府。
  1. instanceOf 和 isPrototype有什么不同荧关?
    都是只要是出現在原型鏈中的構造函數就會判true
console.log(child1 instanceof Child); // true
console.log(child1 instanceof Parent); // true
console.log(child1 instanceof Object); // true

console.log(Parent.prototype.isPrototypeOf(child1)); // true
console.log(Child.prototype.isPrototypeOf(child1)); // true
console.log(Object.prototype.isPrototypeOf(child1)); // true

A.isPrototypeOf(B) 判斷的是A對象是否存在于B對象的原型鏈之中
A instanceof B 判斷的是B.prototype是否存在與A的原型鏈之中

  1. ES6中Class繼承如何實現?
    ES5 的繼承挟纱,實質是先創(chuàng)造子類的實例對象this羞酗,然后再將父類的方法添加到this上面(Parent.apply(this))。
    ES6 的繼承機制完全不同紊服,實質是先創(chuàng)造父類的實例對象this(所以必須先調用super方法)檀轨,然后再用子類的構造函數修改this。
class Component{
    constructor(componentName){
        // console.log(this); // Input {}
        this.componentName = componentName;
    }
    getName(){
        console.log('componentName:', this.componentName);
    }
}

class Input extends Component{
    constructor(name, model){
        // Component.prototype.constructor.call(this, name);
        super(name);
        // 如果不調super報錯:
        // ReferenceError: 
        // Must call super constructor in derived class before accessing 'this' or returning from derived constructor
        this.model = model;
    }
    static myMethod(msg) {
        super.myMethod(msg);
    }
    getModel(){
        console.log('model:', this.model);
        // super作為對象時欺嗤,在普通方法中参萄,指向父類的原型對象;在靜態(tài)方法中煎饼,指向父類讹挎。
        console.log(super.getName); // [Function: getName]
    }
}

const input = new Input('input', 'inputModel');
input.getName(); // componentName: input
input.getModel(); // model: inputModel

參考內容

[JavaScript中的new關鍵詞]https://www.w3cplus.com/javascript/javascript-new-keyword.html
[instanceOf 和 isPrototype]http://www.cnblogs.com/ArthurXml/p/6555509.html
[ES6繼承]http://es6.ruanyifeng.com/#docs/class-extends

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吆玖,隨后出現的幾起案子筒溃,更是在濱河造成了極大的恐慌,老刑警劉巖沾乘,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怜奖,死亡現場離奇詭異,居然都是意外死亡翅阵,警方通過查閱死者的電腦和手機歪玲,發(fā)現死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掷匠,“玉大人滥崩,你說我怎么就攤上這事《镉铮” “怎么了钙皮?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我株灸,道長崇摄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任慌烧,我火速辦了婚禮逐抑,結果婚禮上,老公的妹妹穿的比我還像新娘屹蚊。我一直安慰自己厕氨,他們只是感情好,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布汹粤。 她就那樣靜靜地躺著命斧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘱兼。 梳的紋絲不亂的頭發(fā)上国葬,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天,我揣著相機與錄音芹壕,去河邊找鬼汇四。 笑死,一個胖子當著我的面吹牛踢涌,可吹牛的內容都是我干的通孽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼睁壁,長吁一口氣:“原來是場噩夢啊……” “哼背苦!你這毒婦竟也來了?” 一聲冷哼從身側響起潘明,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤行剂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后钳降,有當地人在樹林里發(fā)現了一具尸體硼讽,經...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年牲阁,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壤躲。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡城菊,死狀恐怖,靈堂內的尸體忽然破棺而出碉克,到底是詐尸還是另有隱情凌唬,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布漏麦,位于F島的核電站客税,受9級特大地震影響况褪,放射性物質發(fā)生泄漏。R本人自食惡果不足惜更耻,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一测垛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秧均,春花似錦食侮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至誉己,卻和暖如春眉尸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巨双。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工噪猾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人炉峰。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓畏妖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親疼阔。 傳聞我的和親對象是個殘疾皇子戒劫,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348