整理面向對象的繼承

階段一

首先創(chuàng)建一個父類的函數方便繼承

function Animal(aniamlType,age){
            this.aniamlType = aniamlType
            this.age = age
        }

然后再創(chuàng)建一個子類用來繼承

function Dog(aniamlType, age, name) {
            Animal.call(this, aniamlType, age)
            this.name = name
        }

只需將this傳進去執(zhí)行一遍Animal函數栅盲,就能得到所有的屬性了湘今。
但是父類prototype的方法并不會被繼承下來!

function Animal(aniamlType, age) {
        this.aniamlType = aniamlType
        this.age = age
    }
    Animal.prototype.eat = function () {
        console.log('eat')
    }
    function Dog(aniamlType, age, name) {
        Animal.call(this, aniamlType, age)
        this.name = name
    }
    var dog1 = new Dog('dog', '18', 'wb')
    dog1.eat()//Uncaught TypeError: dog1.eat is not a function

階段二

由于父類的方法沒辦法繼承剪菱,所以這時候我們就考慮從子類的prototype上來選擇繼承摩瞎。這樣就能讓實例proto指向子類的prototype的時候能夠得到父類的方法和屬性了。
這時候我們將代碼改一改

        function Animal(aniamlType, age) {
            this.play = ['eat','bite','shout']
        }
        Animal.prototype.eat = function () {
            console.log('eat')
        }
        function Dog(aniamlType, age, name) {
            this.aniamlType = aniamlType
            this.age = age
            this.name = name
        }
        Dog.prototype = new Animal()
        var dog1 = new Dog('dog', '18', 'wb')
        dog1.eat() //eat

可以看到這樣就能讓實例得到父類的方法了孝常。
但是當我再創(chuàng)建一個實例的時候旗们,然后修改父類的時候,由于兩個實例的proto是子類的prototype构灸,而子類的prototype引用同一個地址上渴,即父類的實例(new Animal()),所以修改一個實例里面來自父類的對象的時候喜颁,另一個實例的那個對象也會跟著發(fā)生改變

        var dog1 = new Dog('dog', '18', 'wb')
        var dog2 = new Dog('dog', '20', 'wbd')
        dog1.play.push('owwwww')
        console.log(dog1.play)//["eat", "bite", "shout", "owwwww"]
        console.log(dog2.play)//["eat", "bite", "shout", "owwwww"]

這種方法雖然可以繼承父類的方法稠氮,但是改變父類對象的時候,其他實例的這個對象也會跟著改變半开。

階段三

上述兩個階段都有其可取之處隔披,也有缺點。所以我們可以想到寂拆,應該能兩者一起混合使用奢米。于是就有了第三種方案了抓韩。

        function Animal(aniamlType, age) {
            this.aniamlType = aniamlType
            this.age = age
            this.play = ['eat', 'bite', 'shout']
        }
        Animal.prototype.eat = function () {
            console.log('eat')
        }
        function Dog(aniamlType, age, name) {
            Animal.call(this, aniamlType, age, name)//使用階段一來繼承屬性
            this.name = name
        }
        Dog.prototype = new Animal()//使用階段二來繼承方法
        var dog1 = new Dog('dog', '18', 'wb')
        var dog2 = new Dog('dog', '20', 'wbd')
        dog1.play.push('owwwww')
        console.log(dog1.play)//["eat", "bite", "shout", "owwwww"]
        console.log(dog2.play)//["eat", "bite", "shout"]

這時候更改一個實例的時候就不會出現階段三的問題了。
但是子類new鬓长,實例也要new一下谒拴,會增加性能損耗
于是想到直接等于讓子類的prototype = 父類的prototype好了

        Dog.prototype = Animal.prototype

但是這時候問題又來了,子類在prototype上添加的方法會直接影響到父類的prototype涉波,不方便別的子類繼承該父類英上。而且子類的constructor會發(fā)生改變。

        Dog.prototype.cat = function () {
            console.log('cat')
        }
        console.log(Animal.prototype.cat) // function () { console('cat') }
        console.log(dog1.constructor)//function Animal ....

在上面會發(fā)現創(chuàng)建實例的竟然是爺爺啤覆,而不是爸爸苍日。這就亂套了。
所以這時候就需要將子類的prototype復制父類的prototype而不是直接引用了城侧。這時候不僅父類沒有了方法易遣,而且還可以直接修改子類的constructor了

        Dog.prototype = Object.create(Animal.prototype)
        Dog.prototype.cat = function () {
            console.log('cat')
        }
        Dog.prototype.constructor = Dog
        console.log(Animal.prototype.cat) //undefined
        console.log(dog1.constructor) //function Dog

這時候才是完美的面向對象的繼承彼妻。
總結:
1.在子類內部繼承屬性
2.在子類的prototype上復制父類的prototype
3.更改子類prototype.constructor嫌佑,讓其指向自己。


更簡單方便的方法侨歉,使用ES6的Class繼承

        class Animal {
            constructor(aniamlType, age) {
                this.aniamlType = aniamlType
                this.age = age
            }
            eat() {
                console.log('eat')
            }
        }
        class Dog extends Animal {
            constructor(aniamlType, age, name) {
                super(aniamlType, age)
                this.name = name
            }
            cat() {
                console.log('cat')
            }
        }
        var dog1 = new Dog('dog', '18', 'wb')
        console.log(dog1.aniamlType, dog1.age, dog1.name)//dog 18 wb
        dog1.cat()//cat
        dog1.eat()//eat
        console.log(dog1.constructor) //class Dog extends Animal {...}

可以看出ES6的class不用那么復雜了屋摇。直接使用,沒有后顧之憂

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末幽邓,一起剝皮案震驚了整個濱河市炮温,隨后出現的幾起案子,更是在濱河造成了極大的恐慌牵舵,老刑警劉巖柒啤,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異畸颅,居然都是意外死亡担巩,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門没炒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涛癌,“玉大人,你說我怎么就攤上這事送火∪埃” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵种吸,是天一觀的道長弃衍。 經常有香客問我,道長坚俗,這世上最難降的妖魔是什么笨鸡? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任姜钳,我火速辦了婚禮,結果婚禮上形耗,老公的妹妹穿的比我還像新娘哥桥。我一直安慰自己,他們只是感情好激涤,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布拟糕。 她就那樣靜靜地躺著,像睡著了一般倦踢。 火紅的嫁衣襯著肌膚如雪送滞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天辱挥,我揣著相機與錄音犁嗅,去河邊找鬼。 笑死晤碘,一個胖子當著我的面吹牛褂微,可吹牛的內容都是我干的。 我是一名探鬼主播园爷,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼宠蚂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了童社?” 一聲冷哼從身側響起求厕,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扰楼,沒想到半個月后呀癣,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡弦赖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年项栏,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腾节。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡忘嫉,死狀恐怖,靈堂內的尸體忽然破棺而出案腺,到底是詐尸還是另有隱情庆冕,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布劈榨,位于F島的核電站访递,受9級特大地震影響,放射性物質發(fā)生泄漏同辣。R本人自食惡果不足惜拷姿,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一惭载、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧响巢,春花似錦描滔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至伏穆,卻和暖如春拘泞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枕扫。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工陪腌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烟瞧。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓诗鸭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親燕刻。 傳聞我的和親對象是個殘疾皇子只泼,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348