再和“面向?qū)ο蟆闭剳賽?- 繼承(五)

通過上一篇文章想必各位老鐵已經(jīng)熟悉了class了屯远,這篇文章接著介紹繼承。面向?qū)ο罄镒畲蟮奶攸c應(yīng)該就屬繼承了惕耕。一個項目可能需要不斷的迭代、完善诫肠、升級赡突。那每一次的更新你是要重新寫呢,還是在原有的基礎(chǔ)上改吧改吧呢区赵?當(dāng)然惭缰,不是缺心眼的人肯定都會在原來的基礎(chǔ)上改吧改吧,那這個改吧改吧就需要用到繼承了笼才。

第二篇文章里說過原型實例跟構(gòu)造函數(shù)之間的繼承漱受,并且還講了一道推算題。最終我們明白骡送,實例為什么能繼承原型上的內(nèi)容是因為prototype昂羡,所以在ES5里面想要繼承的話就得通過原型,需要對prototype進(jìn)行一頓蹂躪才行摔踱。那到了ES6里面一切就簡單了虐先,像開了掛似的!so easy派敷,哪里不會點哪里蛹批!

繼承

  • class類可以通過extends實現(xiàn)繼承
  • 利用super關(guān)鍵字引入父類的構(gòu)造函數(shù)
  • ES6規(guī)定子類必需在構(gòu)造函數(shù)(constructor)里先調(diào)用super方法
  • 子類能同時繼承父類的共享方法與私有方法
//這個類做為父類('老王')
class OldWang{   
    constructor(work,money){
        this.work=work;
        this.money=money;
    }
    showWork(){
        console.log(`老王是個${this.work},看了我的文章后篮愉,能力達(dá)到了${this.level}腐芍,一個月能掙${this.money}元`);
    }
    static play(){  //這是個私有方法,但子類依然能繼承到
        console.log('大吉大利试躏,今晚吃雞猪勇!不會玩游戲的前端不是個好前端!');
    }
}

//子類繼承父類
class SmallWang extends OldWang{   
    constructor(work,money,level){
        //這里必需先寫super颠蕴,不然會報錯
        super(work,money,level);
        this.level=level;   //只有用了super泣刹,才能使用this
    }
}

//生成實例
const wang=new SmallWang('前端',20000,'T5');
wang.showWork();    //老王是個前端助析,看了我的文章后,能力達(dá)到了T5椅您,一個月能掙20000元
SmallWang.play();   //大吉大利外冀,今晚吃雞!不會玩游戲的前端不是個好前端襟沮!  子類能繼承父類的私有方法

//與ES5里的實例是一致的
console.log(
    Object.getPrototypeOf(SmallWang)===OldWang, //true 子類的原型是OldWang锥惋,也就是說,它是OldWang的實例
    wang instanceof OldWang,        //true
    wang instanceof SmallWang,      //true
);

ES5的繼承开伏,實質(zhì)是先聲明子類膀跌,然后通過call方法將父類的方法添加到子類上,而ES6的繼承機制完全不同固灵。實質(zhì)是聲明了子類后捅伤,子類并沒有this對象,而是利用super方法引入父類的this對象巫玻,再將this修改成子類丛忆,就這么神奇!

new.target

new是生成實例的命令仍秤。ES6new命令引入了一個new.target屬性熄诡,該屬性一般用在構(gòu)造函數(shù)之中

  • new.target返回new命令作用于的那個類
  • 子類繼承父類時,new.target返回子類
class Person{
    constructor(){
        //如果類不是通過new調(diào)用的诗力,就會返回undefined
        if(new.target===undefined){
            throw new Error('請使用new生成實例凰浮!');
        }
        console.log(new.target.name);
    }
}
new Person();   //Person類(返回了new作用于的那個類)
Person();       //有些瀏覽器可以不帶new生成實例,就會拋出一個錯誤

class Man extends Person{
}
new Man();  //Man(子類繼承父類時苇本,new.target會返回子類)


//利用這個特性實現(xiàn)一個不能獨立使用袜茧,必需繼承后才能用的類(像React里的組件)
class Uncle{
    constructor(){
        if(new.target===Uncle){
            throw new Error('這個類不能實例化,只能繼承后再用');
        }
    }
    showUncle(){
        console.log('都是他舅');
    }
}
//new Uncle();  報錯

//通過繼承就可以使用Uncle了
class BigUncle extends Uncle{
    constructor(){
        super();    //引入父類的構(gòu)造函數(shù)瓣窄,必須加不然報錯
        this.uncle='他大舅';
    }
}

//實例
const uncle=new BigUncle();
uncle.showUncle();  //都是他舅

原型

class里的原型關(guān)系相對于ES5里的原型關(guān)系笛厦,ES6對其進(jìn)行了修改,但只修改了子類與父類之間的關(guān)系俺夕,其它的關(guān)系并沒有修改裳凸。

  1. 子類的__proto__,表示構(gòu)造函數(shù)的繼承啥么,指向父類構(gòu)造函數(shù)
  2. 子類prototype屬性的__proto__登舞,表示方法的繼承,指向父類的prototype

ES5里的繼承關(guān)系悬荣,在第二篇文章里詳細(xì)介紹過,再回顧一下:

//ES5的繼承關(guān)系
const str=new String(123);
console.log(
    str.__proto__===String.prototype疙剑,       //true
    String.__proto__===Function.prototype   //true
);  

//可以看到不管實例還是構(gòu)造函數(shù)氯迂,它們的__proto__屬性永遠(yuǎn)都指向原型

ES6與ES5的對比如下:

//ES5
function Ball(){}
function Football(){
    Ball.call(this);    //ES5的繼承
}

//ES6
class Father{};
class Son extends Father{}

//構(gòu)造函數(shù)践叠,關(guān)系沒變
console.log(
    '構(gòu)造函數(shù)',
    Ball.__proto__===Ball.prototype,    //false
    Father.__proto__===Father.prototype,//false
    
    Ball.__proto__===Function.prototype,    //true
    Father.__proto__===Function.prototype   //true
);

//實例,關(guān)系沒變
console.log(
    '實例',
    new Ball().__proto__===Ball.prototype,      //true
    new Father().__proto__===Father.prototype   //true
);

//子類嚼蚀,關(guān)系變了
console.log(
    '子類的__proto__',
    Football.__proto__===Ball,  //false ES5
    Football.__proto__===Function.prototype,//true  ES5
    
    Son.__proto__===Father,     //true ES6
    Son.__proto__===Father.prototype,   //false ES6
    
    //ES6的變化為:子類的__proto__指向父類
);

console.log(
    '子類的prototype的__proto__屬性',
    Football.prototype.__proto__===Ball.prototype,  //false ES5
    Football.prototype.__proto__===Object.prototype,//true  ESS
    
    Son.prototype.__proto__===Object.prototype,     //false ES6
    Son.prototype.__proto__===Father.prototype,     //true ES6
    
    //ES6的變化為:子類的prototype的__proto__屬性指向父類的prototype
);

由此可以看出ES6只修改了子類跟父類間的原型關(guān)系禁灼,其它的不受影響。那至于ES6對這兩條關(guān)系做了修改的原因跟ES6的繼承機制有關(guān)系轿曙,ES6內(nèi)部的繼承用的是Object.setPrototypeOf方法(ES6新增的方法弄捕,作用是把第一個參數(shù)的原型設(shè)置成第二個參數(shù)),以下為內(nèi)部過程:

{
    class Father{};
    class Son{};
    
    //son的實例繼承Father的實例导帝,內(nèi)部會執(zhí)行下面的代碼
    Object.setPrototypeOf(Son.prototype,Father.prototype);
    //等同于Son.prototype.__proto__=Father.prototype;所以得出結(jié)果:子類prototype屬性的__proto__屬性守谓,表示方法的繼承,指向父類的prototype屬性
    
    //son繼承Father的私有屬性您单,內(nèi)部會執(zhí)行下面的代碼
    Object.setPrototypeOf(Son,Father);
    //等同于Son.__proto__=Father;所以得出結(jié)果:子類的__proto__屬性斋荞,表示構(gòu)造函數(shù)的繼承,指向父類
}

為什么用了setPrototypeOf后虐秦,等價于把第一個參數(shù)的__proto__的值設(shè)置成第二個參數(shù)平酿?是因為setPrototypeOf方法的內(nèi)部是這樣的:

//setPrototypeOf方法內(nèi)部主要代碼
Object.setPrototypeOf=function(obj,proto){
    obj.__proto__=proto;
    return obj;
}

下一篇文章介紹super關(guān)鍵字

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市悦陋,隨后出現(xiàn)的幾起案子蜈彼,更是在濱河造成了極大的恐慌,老刑警劉巖俺驶,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幸逆,死亡現(xiàn)場離奇詭異,居然都是意外死亡痒钝,警方通過查閱死者的電腦和手機秉颗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來送矩,“玉大人蚕甥,你說我怎么就攤上這事《拜” “怎么了菇怀?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長晌块。 經(jīng)常有香客問我爱沟,道長,這世上最難降的妖魔是什么匆背? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任呼伸,我火速辦了婚禮,結(jié)果婚禮上钝尸,老公的妹妹穿的比我還像新娘括享。我一直安慰自己搂根,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布铃辖。 她就那樣靜靜地躺著剩愧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娇斩。 梳的紋絲不亂的頭發(fā)上仁卷,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音犬第,去河邊找鬼锦积。 笑死,一個胖子當(dāng)著我的面吹牛瓶殃,可吹牛的內(nèi)容都是我干的充包。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼遥椿,長吁一口氣:“原來是場噩夢啊……” “哼基矮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起冠场,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤家浇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后碴裙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钢悲,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年舔株,在試婚紗的時候發(fā)現(xiàn)自己被綠了莺琳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡载慈,死狀恐怖惭等,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情办铡,我是刑警寧澤辞做,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站寡具,受9級特大地震影響秤茅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜童叠,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一框喳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦帖努、人聲如沸撰豺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亩歹,卻和暖如春匙监,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背小作。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工亭姥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人顾稀。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓达罗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親静秆。 傳聞我的和親對象是個殘疾皇子粮揉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

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