我們?nèi)粘i_發(fā)都會(huì)用到ES6, 比如我們擼React昼蛀,寫組件肯定擼過class XX extends React.Component. constructor(){super(xx)}之類的棕兼。
今天就來看看這個(gè)class陡舅,我們知道JS里本身是沒有class這個(gè)概念,其他語言比如java伴挚,python是天生就有class的靶衍,JS肯定不服啊,所以在ES6里就引入了class茎芋,那么是class就真的是class嗎颅眶?No,此class非彼class田弥,用的babel的同學(xué)肯定會(huì)知道涛酗,當(dāng)我們打開編譯后的es6代碼,實(shí)際就是es5偷厦,里面并沒有class商叹,還是prototype什么那些一堆亂七八糟的玩意兒,說白了只泼,class只是一個(gè)語法糖剖笙,方便我們開發(fā)寫代碼而已。
好辜妓,那我們就來看看什么是真正的繼承吧枯途。
Type 1: 原型鏈的方式可以實(shí)現(xiàn)忌怎,talk is cheap, show me the code.亮代碼
function Taylor () {
this.name = 'Taylor'
this.price = 7777
}
function Guitar () {
this.dalao= '雨神'
}
Taylor.prototype = new Guitar()
const guitar = new Taylor()
我想買一把吉他,吉他有很多品牌酪夷,比如泰勒馬丁雅馬哈各種榴啸,精挑細(xì)選最后看中了泰勒這個(gè)吉他品牌,就先定義一個(gè)子類叫泰勒晚岭,接著我們定義父類就是Guitar鸥印。
接下來就是關(guān)鍵的一步,Taylor.prototype = new Guitar()坦报,將Guitar的實(shí)例賦給Taylor的顯式原型prototype,這樣就完成了最基本的原型鏈繼承库说。我們可以來試一下,再控制臺(tái)輸入以上代碼并執(zhí)行片择,然后
console.log(guitar.dalao)
控制臺(tái)會(huì)輸出雨神大佬潜的,在Taylor的定義里并沒有dalao的屬性,而現(xiàn)在我們卻可以輸出dalao這個(gè)屬性字管,就是通過原型鏈找到的啰挪,這就說明Taylor繼承了Guitar,也說明了雨神不僅是泰勒dalao嘲叔,不管任何品牌吉他的都是dalao,是我等菜雞膜拜的大神亡呵。
好了,言歸正傳硫戈,這種原型鏈的方式也有缺點(diǎn)锰什,比如如果父類的屬性是一個(gè)引用類型,在一個(gè)子類實(shí)例中修改了這個(gè)屬性之后新創(chuàng)建的子類實(shí)例也會(huì)被永久修改了丁逝。還有就是不能直接給父類構(gòu)造函數(shù)傳參汁胆,因?yàn)闀?huì)影響新建實(shí)例對(duì)象。
Type 2: 構(gòu)造函數(shù)的方式可以實(shí)現(xiàn)果港,talk is cheap, show me the code.亮代碼
function Guitar (name) {
this.dalao= name
this.songs = []
}
function Taylor (dalao) {
this.name = 'Taylor'
this.price = 7777
Guitar.call(this, dalao)
}
const guitar = new Taylor('雨神')
和上面一樣沦泌,我們改成構(gòu)造函數(shù)的方式實(shí)現(xiàn)繼承,關(guān)鍵的一步辛掠,Guitar.call(this, '雨神')谢谦,改變了父類Guitar的執(zhí)行上下文this指向,讓this指向子類萝衩,換句話說就是把父類構(gòu)造函數(shù)在子類構(gòu)造函數(shù)里執(zhí)行一遍回挽。而且解決了之前原型鏈繼承存在的問題,一個(gè)就是不能直接父類構(gòu)造函數(shù)傳參猩谊,我們給Guitar定義了一個(gè)形參name千劈,在new Taylor('雨神')里我們傳入雨神這個(gè)實(shí)參,然后我們和上面一樣在控制臺(tái)輸出console.log(guitar.dalao)
控制臺(tái)也一樣會(huì)輸出雨神大佬牌捷,然后我們可以做下改動(dòng)墙牌,Guitar.call(this, '小老弟60')涡驮,重復(fù)上面步驟,控制臺(tái)會(huì)輸出'小老弟60'.
第二個(gè)問題就是父類引用類型屬性喜滨,我這里放了了一個(gè)songs=[]一個(gè)空數(shù)組捉捅。然后我們給guitar實(shí)例的songs做加點(diǎn)東西。
guitar.songs.push('盜將行')
我們年會(huì)表演的曲子虽风,很好聽的棒口,強(qiáng)烈推薦,沒聽過可以試試辜膝。然后我們新建一個(gè)Taylor的實(shí)例无牵,const guitar222= new Taylor() console.log(guitar222.songs)
控制臺(tái)輸出一個(gè)[],發(fā)現(xiàn)之前我們的操作并沒有影響到后來新建的實(shí)例對(duì)象厂抖,這就解決了原型鏈的兩個(gè)缺點(diǎn)茎毁,當(dāng)然構(gòu)造函數(shù)模式 也有缺點(diǎn),就是父類原型里定義的屬性子類是無法繼承的忱辅。
所以充岛,我們?nèi)∑渚A去其糟粕,把二者合二為一耕蝉,誕生了第三種繼承方式,組合繼承夜只,就是把原型鏈和構(gòu)造函數(shù)組合在一起實(shí)現(xiàn)繼承垒在。
Type 3: 組合繼承的方式可以實(shí)現(xiàn),talk is cheap, show me the code.亮代碼
function Guitar (name) {
this.dalao= name
this.songs = []
}
function Taylor (dalao) {
this.name = 'Taylor'
this.price = 7777
Guitar.call(this, dalao)
}
Guitar.prototype.band = 'HikWestlife'
Taylor.prototype = new Guitar()
Taylor.prototype.constructor = Taylor
const guitar = new Taylor('雨神')
這就是組合繼承扔亥,同時(shí)我們把Taylor.prototype.constructor的構(gòu)造器指向Taylor场躯。然而還是不夠完美,因?yàn)楦割惖臉?gòu)造函數(shù)執(zhí)行了兩次旅挤,為了更好的性能踢关,我們發(fā)明了終極解放方案,寄生組合式繼承粘茄。
Type 4: 寄生繼承的方式可以實(shí)現(xiàn)签舞,talk is cheap, show me the code.亮代碼
function Guitar (name) {
this.dalao= name
this.songs = []
}
function Taylor (dalao) {
this.name = 'Taylor'
this.price = 7777
Guitar.call(this, dalao)
}
Guitar.prototype.band = 'HikWestlife'
Taylor.prototype = Object.create(Guitar.prototype)
Taylor.prototype.constructor = Taylor
const guitar = new Taylor('雨神')
一起來試驗(yàn)一下,我們?cè)诳刂婆_(tái)輸出console.log(guitar.band)
發(fā)現(xiàn)會(huì)輸出"HikWestlife"柒瓣,一樣實(shí)現(xiàn)了組合繼承的功能儒搭,而且還只執(zhí)行了一次構(gòu)造函數(shù)。
好了芙贫,這就是class的真面目搂鲫,放假了。磺平。過年~