成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

Airmusic / 1548人閱讀

摘要:面向?qū)ο罄镒畲蟮奶攸c應該就屬繼承了。在第二篇文章里說過原型實例跟構(gòu)造函數(shù)之間的繼承,并且還講了一道推算題。

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

在第二篇文章里說過原型實例跟構(gòu)造函數(shù)之間的繼承,并且還講了一道推算題。最終我們明白,實例為什么能繼承原型上的內(nèi)容是因為prototype,所以在ES5里面想要繼承的話就得通過原型,需要對prototype進行一頓蹂躪才行。那到了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},看了我的文章后,能力達到了${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();    //老王是個前端,看了我的文章后,能力達到了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對其進行了修改,但只修改了子類與父類之間的關(guān)系,其它的關(guān)系并沒有修改。

子類的__proto__,表示構(gòu)造函數(shù)的繼承,指向父類構(gòu)造函數(shù)

子類prototype屬性的__proto__,表示方法的繼承,指向父類的prototype

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

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

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

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)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96656.html

相關(guān)文章

  • 再和面向對象戀愛 - 圖片預加載組件(七)

    摘要:源碼下載至此再和面向?qū)ο笳剳賽巯盗形恼乱呀?jīng)全部更新完畢寫文章不易,且行且珍惜 再和面向?qū)ο笳剳賽?- 對象簡介(一)再和面向?qū)ο笳剳賽?- 對象相關(guān)概念(二)再和面向?qū)ο笳剳賽?- 面向?qū)ο缶幊谈拍睿ㄈ┰俸兔嫦驅(qū)ο笳剳賽?- class(四)再和面向?qū)ο笳剳賽?- 繼承(五)再和面向?qū)ο笳剳賽?- super(六) 通過前面的六篇文章已經(jīng)把ES6的面向?qū)ο蟾蠡镎f清楚了,大家最關(guān)心的...

    caoym 評論0 收藏0
  • 再和面向對象戀愛 - class(四)

    摘要:在上一篇文章里我介紹了一下面向?qū)ο缶幊痰母拍?,在最后終于喜出望外看到了提供了類的概念了。而到了里面真正的類與構(gòu)造函數(shù)現(xiàn)在是分離的,通過上面的代碼可以看出來,這種寫法正是面向?qū)ο蟮恼y(tǒng)寫法。 在上一篇文章里我介紹了一下面向?qū)ο缶幊痰母拍?,在最后終于喜出望外看到了ES6提供了類的概念了。那這個類如何去用,是這篇文章的主題。ES6給我們提供了一個class關(guān)鍵字。這個關(guān)鍵字跟以前的var l...

    劉東 評論0 收藏0
  • 再和面向對象戀愛 - 對象相關(guān)概念(二)

    摘要:所有的對象都是由構(gòu)造函數(shù)創(chuàng)建的對象哪來的構(gòu)造函數(shù)生的。而普通函數(shù)不能生成對象不孕不育,構(gòu)造函數(shù)可以生成對象有生育能力。別急,記住那句話永遠指向?qū)嵗龑ο髮臉?gòu)造函數(shù)的,那就先看實例對象是誰。 上一篇文章把對象的概念講解了一下,這篇文章要重點解釋最讓大家犯迷糊的一些概念,包括 構(gòu)造函數(shù) 實例 繼承 構(gòu)造函數(shù)的屬性與方法(私有屬性與方法) 實例的屬性與方法(共享屬性與方法) protot...

    qpwoeiru96 評論0 收藏0
  • 再和面向對象戀愛 - super(六)

    摘要:同時彈出的結(jié)果是指向了子類,又說明雖然調(diào)用的是父類的構(gòu)造函數(shù),但是調(diào)用完后會指向子類,指向也被改成了子類的實例。 在上一篇文章里介紹了繼承,那其中說過一個很關(guān)鍵的東西想要繼承子類里里必需先調(diào)用一個super方法。而super的作用絕對是價值連城!同時super的作用還有多種,并且跟你的使用環(huán)境有關(guān)系。 1、當作函數(shù)使用 super被當作函數(shù)使用,這種情況是最普遍的,上一篇文章里已經(jīng)使用...

    Towers 評論0 收藏0
  • 再和面向對象戀愛 - 面向對象編程概念(三)

    摘要:說到底面向?qū)ο蟛攀浅绦蛘Z言的根本。其實面向?qū)ο缶幊陶f的就是自定義對象。里并沒有類的概念,所以嚴格上來講這是個假的面向?qū)ο罄锏拿嫦驅(qū)ο缶幊态F(xiàn)在好了,終于聽到別人鄙視我們了,給我們提供了類這個概念,其實是向傳統(tǒng)語言更靠齊了。 通過前兩篇文章,我們了解了對象的概念以及面向?qū)ο罄锏南嚓P(guān)概念等知識,那前面說了對象分類里的前兩種,這篇文章要詳細去說第三種自定義對象,那真正的好戲這就來了! 面向?qū)ο?..

    Cruise_Chan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<