看完這篇文章,你應(yīng)該懂什么叫繼承了吧

說(shuō)到繼承呢限嫌?肯定有很多做java的朋友都覺(jué)得是一個(gè)比較簡(jiǎn)單的東西了靴庆。畢竟面向?qū)ο蟮娜筇卣骶褪牵悍庋b、繼承和多態(tài)嘛怒医。但是真正對(duì)于一個(gè)javascript開(kāi)發(fā)人員來(lái)說(shuō)炉抒,很多時(shí)候其實(shí)你使用了繼承,但其實(shí)你不知道這叫繼承稚叹。今天我就借這篇文章來(lái)談一談繼承在前端的幾種實(shí)現(xiàn)方式焰薄。

一拿诸、 原型繼承

function Animal(name = 'animal'){
    this.name = name
}
Animal.prototype.eat = function(food){
    console.log('dasdsa')
    return `${this.name} eat ${food}`;
}

function Dog(){
}
Dog.prototype = new Animal();

var instance = new Dog();
instance.name = 'dog';
console.log(instance.eat('bone'));
console.log(instance instanceof Dog); // true
console.log(instance instanceof Animal); // true

但是原型繼承有有有些缺點(diǎn),來(lái)看下面一段代碼:

function Animal(name = 'animal'){
    this.name = name
    this.skinColors = ['black','white']
}
Animal.prototype.eat = function(food){
    return `${this.name} eat ${food}`;
}

function Dog(){
}
Dog.prototype = new Animal();

var instance = new Dog();
instance.name = 'keji';
instance.skinColors.push('red');
console.log(instance.eat('bone'));
console.log(instance instanceof Dog); // true
console.log(instance instanceof Animal); // true

var instance1 = new Dog()
console.log(instance1.skinColors) // [ 'black', 'white', 'red' ]

從上面的代碼塞茅,我們可以清楚的發(fā)現(xiàn):所有的實(shí)例都會(huì)公用一個(gè)原型鏈亩码,如果一個(gè)實(shí)例中修改原型 那么所有實(shí)例的值都會(huì)被修改。

二野瘦、 構(gòu)造函數(shù)繼承

針對(duì)前面原型鏈繼承可能會(huì)存在公用一個(gè)原型鏈的問(wèn)題描沟,那么我們可以給大家介紹一種方式:構(gòu)造函數(shù)的繼承。構(gòu)造函數(shù)的繼承相當(dāng)于將父類復(fù)制給子類鞭光。

function Animal(name = 'animal'){
    this.name = name
    this.skinColors = ['black','white']
}
Animal.prototype.eat = function(food){
    return `${this.name} eat ${food}`;
}

function Dog(){
    Animal.call(this);
}

var instance = new Dog();
instance.name = 'keji';
instance.skinColors.push('red');
console.log(instance.eat('bone')); // TypeError: instance.eat is not a function
console.log(instance instanceof Dog); // true
console.log(instance instanceof Animal); // true

var instance1 = new Dog();
console.log(instance1.skinColors); // [ 'black', 'white' ]

但是這種方法也有自己缺點(diǎn):

  • 不能繼承原型上面的屬性和方法
  • 復(fù)制的處理吏廉,相當(dāng)于在子類中實(shí)現(xiàn)了所有父類的方法,影響子類的性能衰猛。

三迟蜜、 組合繼承

原型鏈繼承能繼承父類原型鏈上的屬性,但是可能會(huì)存在篡改的問(wèn)題啡省;而構(gòu)造函數(shù)繼承不會(huì)存在篡改的問(wèn)題娜睛,但是不能繼承原型上面的屬性。那么我們是不是可以將兩者進(jìn)行結(jié)合呢卦睹?

function Animal(name = 'animal'){
    this.name = name
    this.skinColors = ['black','white']
}
Animal.prototype.eat = function(food){
    return `${this.name} eat ${food}`;
}

function Dog(){
    Animal.call(this);
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;


var instance = new Dog();
instance.name = 'keji';
instance.skinColors.push('red');
console.log(instance.eat('bone'));
console.log(instance.skinColors) // [ 'black', 'white', 'red' ]
console.log(instance instanceof Dog); // true
console.log(instance instanceof Animal); // true

var instance1 = new Dog()
console.log(instance1.skinColors) // [ 'black', 'white' ]

這種方法呢畦戒?調(diào)用了兩次父類的構(gòu)造函數(shù),有些許損耗性能结序,并且子類的構(gòu)造函數(shù)的屬性會(huì)和原型上面的屬性相重合障斋。(優(yōu)先原用構(gòu)造函數(shù)的屬性)

四、 原型式繼承

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


let Programmer = {
    features:["tutou","jiaban","single"]
}

// 方式一:最原始的做法
var programmer1 = object(Programmer);
programmer1.features.push('meiqian');
console.log(programmer1.features); // [ 'tutou', 'jiaban', 'single', 'meiqian' ]
var programmer2 = object(Programmer);
console.log(programmer2.features); // [ 'tutou', 'jiaban', 'single', 'meiqian' ]

// 方式二 es中的Object.create
var programmer3 = Object.create(Programmer);
console.log(programmer3.features); // [ 'tutou', 'jiaban', 'single', 'meiqian' ]

從上面的代碼很明顯的可以發(fā)現(xiàn):和構(gòu)造函數(shù)繼承一樣也存在被篡改的可能徐鹤,并且也不能傳遞參數(shù)垃环。

五、 寄生式繼承

在原型式繼承的基礎(chǔ)上面增強(qiáng)了對(duì)象返敬,并返回構(gòu)造函數(shù)遂庄。

function pFactory(obj){
    let clone = Object.create(obj);
    clone.motto = function(){
        console.log('hardworking and not lazy!!')
    }
    return clone;
}

var programmer1 = new pFactory(Programmer);
console.log(programmer1.motto()); // hardworking and not lazy!!
console.log(programmer1.features); // [ 'tutou', 'jiaban', 'single' ]

這種繼承的方法同樣和原型繼承一樣,存在被篡改的可能劲赠。

六涛目、 寄生組合式繼承

前面說(shuō)了這么多,每種繼承方式都有自己的優(yōu)點(diǎn)和缺點(diǎn)凛澎,那么是不是可以將這些繼承的方式做一個(gè)合并:以他之長(zhǎng)補(bǔ)己之短呢霹肝?來(lái)看下面一段代碼:

function Animal(name = 'animal'){
    this.name = name
    this.skinColors = ['black','white']
}
Animal.prototype.eat = function(food){
    return `${this.name} eat ${food}`;
}

function inheritPrototype(subType, superType){
  var prototype = Object.create(superType.prototype);
  prototype.constructor = subType; 
  subType.prototype = prototype;
}


function Dog(name,sound){
    Animal.call(this,name);
    this.sound = sound;
}

inheritPrototype(Dog,Animal);

Dog.prototype.getSound = function(){
    console.log(`${this.name} ${this.sound}`);
}

var instance = new Dog('keji','wangwangwang!!!');
instance.skinColors.push('red');
console.log(instance.eat('bone'));
console.log(instance.skinColors) // [ 'black', 'white', 'red' ]
console.log(instance instanceof Dog); // true
console.log(instance instanceof Animal); // true
console.log(instance.getSound()) // keji wangwangwang!!!

var instance1 = new Dog('haha','wangwang!!!')
console.log(instance1.skinColors) // [ 'black', 'white' ]
console.log(instance1.getSound()) // haha wangwang!!!

這個(gè)例子的效率的體現(xiàn)在它只調(diào)用了一次父類的構(gòu)造函數(shù),這很大程度上面減少創(chuàng)建了不必要多余的屬性塑煎。并且還能繼承原型鏈上面的方法沫换。這個(gè)方法是現(xiàn)在庫(kù)的實(shí)現(xiàn)方法。

七轧叽、 es6的繼承方法

class Animal {
    constructor(name){
        this.name = name;
    }

    get getName(){
        return this.animalName()
    }

    animalName(){
        return this.name;
    }

}

class Dog extends Animal{
    constructor(name,sound){
        super(name);
        this.sound = sound;
    }
    get animalFeature(){
        return `${this.getName} ${this.sound}`
    }
}

let dog = new Dog('keji','wangwangwang!');
console.log(dog.animalFeature); // keji wangwangwang!

其實(shí)我們曉得苗沧,class語(yǔ)法也是由es5語(yǔ)法來(lái)寫(xiě)的刊棕,其繼承的方法和寄生組合式繼承的方法一樣。關(guān)于es6的類待逞,我在代碼自檢的時(shí)候遇到的兩個(gè)重點(diǎn)甥角,值得注意下的是:

  • 函數(shù)聲明會(huì)提升,類聲明不會(huì)识樱。
  • ES5的繼承實(shí)質(zhì)上是先創(chuàng)建子類的實(shí)例對(duì)象嗤无,然后再將父類的方法添加到this上。但是es6是先創(chuàng)建父類的實(shí)例對(duì)象this怜庸,然后再用子類的構(gòu)造函數(shù)修改this当犯。

說(shuō)在最后

好像什么都沒(méi)寫(xiě)就差不多快12點(diǎn)了,最近在瘋狂的復(fù)習(xí)割疾。但是卻發(fā)現(xiàn)越學(xué)東西越多嚎卫,感覺(jué)有點(diǎn)學(xué)不完的意味在里面 外加上最近好像有點(diǎn)高考考砸之后的失眠綜合癥,搞的我整個(gè)人都不怎么舒服宏榕。明明高考都過(guò)去差不多6年了拓诸,還一直困擾著我,賊恐怖麻昼,算了 算了 先不寫(xiě)了 睡覺(jué)去了奠支。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市抚芦,隨后出現(xiàn)的幾起案子倍谜,更是在濱河造成了極大的恐慌,老刑警劉巖叉抡,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尔崔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡褥民,警方通過(guò)查閱死者的電腦和手機(jī)您旁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)轴捎,“玉大人,你說(shuō)我怎么就攤上這事蚕脏≌旄保” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵驼鞭,是天一觀的道長(zhǎng)秦驯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)挣棕,這世上最難降的妖魔是什么译隘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任亲桥,我火速辦了婚禮,結(jié)果婚禮上固耘,老公的妹妹穿的比我還像新娘题篷。我一直安慰自己,他們只是感情好厅目,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布番枚。 她就那樣靜靜地躺著,像睡著了一般损敷。 火紅的嫁衣襯著肌膚如雪葫笼。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天拗馒,我揣著相機(jī)與錄音路星,去河邊找鬼。 笑死诱桂,一個(gè)胖子當(dāng)著我的面吹牛洋丐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播访诱,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼垫挨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了触菜?” 一聲冷哼從身側(cè)響起九榔,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涡相,沒(méi)想到半個(gè)月后哲泊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡催蝗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年切威,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丙号。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡先朦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出犬缨,到底是詐尸還是另有隱情喳魏,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布怀薛,位于F島的核電站刺彩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜创倔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一嗡害、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧畦攘,春花似錦霸妹、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至朗徊,卻和暖如春首妖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爷恳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工有缆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人温亲。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓棚壁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親栈虚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子袖外,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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