在上一篇 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上還有其他一些關於前端的教程和元件,有興趣的童鞋可以看看,你們的支援就是我最大的動力。