JS中的繼承(下)

noahlam發表於2018-05-04

在上一篇 JS中的繼承(上) 我們介紹了3種比較常用的js繼承方法,如果你沒看過,那麼建議你先看一下,因為接下來要寫的內容, 是建立在此基礎上的.另外本文作為我個人的讀書筆記,才疏學淺,如有錯誤,敬請指正.

接下來我們要介紹另外3種相對比較奇葩的繼承

一. 原型式繼承

function clone (proto) {
    function F () {}
    F.prototype = proto
    return new F()
}
複製程式碼

clone 內部首先是建立了一個空的建構函式F,然後把F的prototype指向引數proto,最後返回一個F的例項物件,完成繼承. 原型式繼承看起來跟原型繼承很像,事實上,兩者因為都是基於prototype繼承的,所以也有一些相同的特性,比如引用屬性共享問題, 那原型式繼承原型繼承有什麼區別呢? 一個比較明顯的區別就是clone函式接收的引數不一定要是建構函式,也可以是其他任何物件, 這樣我們就相當於是淺複製了一個物件.

es5的Object.create()函式,就是基於原型式繼承的

原型式繼承是道格拉斯-克羅克福德 2006 年在 Prototypal Inheritance in JavaScript一文中提出的

二. 寄生式繼承

寄生式繼承其實就是在原型式繼承的基礎上,做了一些增強.

function cloneAndStrengthen(proto){
    function F () {}
    F.prototype = proto
    let f = new F()
    f.say = function() { 
        console.log('I am a person')
    }
    return f
}
複製程式碼

我們看到上面的程式碼,跟原型式繼承比,差別就是:在例項物件f返回之前,給f新增了一個say函式. 但是這樣在例項物件上新增的引用屬性(比如函式),跟建構函式模式一樣, 例項物件的引用型別屬性無法共享,儘管這既是缺點也是優點.

三. 寄生組合式繼承
上一篇我們提到的組合繼承其實也有個缺點,就是父類建構函式裡面的程式碼會執行2遍,第一遍是在原型繼承的時候例項化父類, 第二遍是在子類的建構函式裡面借用父類的建構函式,我們可以用寄生組合式繼承來解決這個問題

function inherit(sub, super){
    let prototype = clone(super.prototype)
    prototype.constructor = sub    
    sub.prototype = prototype      
}
複製程式碼

這樣我們就實現了一個寄生組合式繼承的函式inherit,接下來我們來使用一下:

function Person(name){}

function Student(){
    SuperType.call(this)
}

inherit(Student, Student)
複製程式碼

我們用 inherit 函式替換了 Student.prototype = new Person(),從而避免了執行 new Person().

書上說: 寄生組合式繼承是引用型別最理想的繼承正規化.

關於js的繼承就介紹到這裡,感謝收看,如果覺得本文對您有用,請給本文的github加個star,萬分感謝, 另外,github上還有其他一些關於前端的教程和元件,有興趣的童鞋可以看看,你們的支援就是我最大的動力。

相關文章