




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第一文詳解如何用原型鏈的方式實(shí)現(xiàn)JS繼承目錄原型鏈?zhǔn)鞘裁赐ㄟ^(guò)構(gòu)造函數(shù)創(chuàng)建實(shí)例對(duì)象用原型鏈的方式實(shí)現(xiàn)繼承方法1:Object.create方法2:直接修改[[prototype]]方法3:使用父類的實(shí)例總結(jié)今天講一道經(jīng)典的原型鏈面試題。
原型鏈?zhǔn)鞘裁?/p>
JavaScript中,每當(dāng)創(chuàng)建一個(gè)對(duì)象,都會(huì)給這個(gè)對(duì)象提供一個(gè)內(nèi)置對(duì)象[[Prototype]]。這個(gè)對(duì)象就是原型對(duì)象,[[Prototype]]的層層嵌套就形成了原型鏈。
當(dāng)我們?cè)L問(wèn)一個(gè)對(duì)象的屬性時(shí),如果自身沒(méi)有,就會(huì)通過(guò)原型鏈向上追溯,找到第一個(gè)存在該屬性原型對(duì)象,取出對(duì)應(yīng)值。
當(dāng)然原型鏈不是無(wú)止境的,和單鏈表一樣,最后一個(gè)原型對(duì)象的值是null,原型鏈的所有對(duì)象都找不到指定的屬性時(shí),我們會(huì)拿到undefined。
[[Prototype]]雖然無(wú)法通過(guò)腳本進(jìn)行訪問(wèn),但大多數(shù)瀏覽器提供了__proto__屬性來(lái)訪問(wèn)這個(gè)內(nèi)置對(duì)象,但它并不是標(biāo)準(zhǔn),無(wú)法兼容所有瀏覽器。
下面來(lái)舉幾個(gè)例子,讓讀者對(duì)原型鏈有一個(gè)直觀的認(rèn)識(shí):
通過(guò)對(duì)象字面量聲明a={}時(shí),a的[[prototype]]就是Ototype。此時(shí)的原型鏈?zhǔn)牵篴-Ototype-null。這里有個(gè)易錯(cuò)點(diǎn),就是以為a的上一個(gè)原型對(duì)象是Object,其實(shí)并不對(duì),Object其實(shí)只是一個(gè)構(gòu)造函數(shù)。聲明數(shù)組arr=[1,2,4],它的原型鏈則是arr-Atotype-Ototype-null。Object.create(null)甚至能夠創(chuàng)建一個(gè)連[[prototype]]都沒(méi)有的真正的空對(duì)象,一般用于做字符串哈希表,比如vue源碼里就能經(jīng)??吹?。
通過(guò)構(gòu)造函數(shù)創(chuàng)建實(shí)例對(duì)象
在JavaScript中,一個(gè)函數(shù)會(huì)在new關(guān)鍵字的配合下成為構(gòu)造函數(shù)。也就是說(shuō),任何一個(gè)函數(shù)都可以成為構(gòu)造函數(shù)。
當(dāng)聲明一個(gè)構(gòu)造函數(shù)時(shí),它會(huì)有一個(gè)屬性名為prototype的對(duì)象(和[[prototype]]是不同的東西),這個(gè)對(duì)象就是原型對(duì)象。這個(gè)對(duì)象的constructor又反過(guò)來(lái)指向構(gòu)造函數(shù)。
當(dāng)我們對(duì)使用new關(guān)鍵字創(chuàng)建對(duì)象,被創(chuàng)建的對(duì)象的[[prototype]]會(huì)指向這個(gè)prototype。
functionRect(){}
constrect=newRect()
rect.__proto__===Rtotype//true
Rtotype.constructor===Rect//true
只要是通過(guò)newRect()創(chuàng)建的對(duì)象,無(wú)論多少次,它的[[prototype]]都是指向Rtotype。另外,Rtotype指向的是Ototype。
這樣,通過(guò)給構(gòu)造函數(shù)的原型對(duì)象(Rtotype)添加一些方法(如Rtotype.draw),就能讓創(chuàng)建的多個(gè)實(shí)例對(duì)象共享同一個(gè)方法,減少內(nèi)存的使用。
用原型鏈的方式實(shí)現(xiàn)繼承
理解了構(gòu)造函數(shù)如何影響創(chuàng)建的實(shí)例的原型鏈后,我們來(lái)探討一下核心問(wèn)題,如何使用原型鏈來(lái)實(shí)現(xiàn)繼承。
假設(shè)我們有一個(gè)Shape構(gòu)造函數(shù)(父類)和Rect構(gòu)造函數(shù)(子類)。代碼如下:
//父類
functionShape(){}
Stotype.draw=function(){
console.log('ShapeDraw')
Stotype.clear=function(){
console.log('ShapeClear')
//子類
functionRect(){}
實(shí)現(xiàn)繼承的代碼放這里
Rtotype.draw=function(){
console.log('RectDraw')
}
通過(guò)前面的學(xué)習(xí),我們知道,正常情況下使用newRect創(chuàng)建的實(shí)例對(duì)象,它的原型鏈?zhǔn)沁@樣的:
rect-Rtotype-Otoype-null
現(xiàn)在我們要實(shí)現(xiàn)的繼承,其實(shí)就是在原型鏈中間再加一個(gè)原型對(duì)象Stotype。對(duì)此我們需要對(duì)Rtotype進(jìn)行特殊的處理。
方法1:Object.create
Rtotype=Object.create(Stotype)
Rtotype.constructor=Rect//選用,如果要用到constructor
Rtotype.constructor=Rect//選用,如果要用到constructor
Object.create(proto)是個(gè)神奇的方法,它能夠創(chuàng)建一個(gè)空對(duì)象,并設(shè)置它的[[prototype]]為傳入的對(duì)象。
因?yàn)槲覀儫o(wú)法通過(guò)代碼的方式給[[prototype]]屬性賦值,所以使用了Object.create方法作為替代。
因?yàn)镽totype指向了另一個(gè)新的對(duì)象,所以把constructor給丟失了,可以考慮把它放回來(lái),如果你要用到的話。
缺點(diǎn)是替換掉了原來(lái)的對(duì)象。
方法2:直接修改[[prototype]]
如果就是不想使用新對(duì)象,只想修改原對(duì)象,可以使用廢棄的__proto__屬性,但不推薦。
不過(guò)另外還有一個(gè)方法Object.setPrototypeOf()可以修改對(duì)象的[[prototype]],但因?yàn)樾阅艿膯?wèn)題,也不推薦使用。
Object.setPrototypeOf(Rtotype,Stotype)
//或
Rtotype.__proto__=Stotype
都不推薦使用,但確實(shí)能用。
方法3:使用父類的實(shí)例
Rtotype=newShape()
形成的原型鏈為:
rect-shape(替代掉原來(lái)的Rtotype)-Stotype-Ototype-null
基本能用,缺點(diǎn)是會(huì)產(chǎn)生副作用,就是執(zhí)行newShap()可能會(huì)出現(xiàn)副作用,比如給創(chuàng)建的對(duì)象添加了一些屬性、發(fā)送了請(qǐng)求之類的,完全取決于構(gòu)造函數(shù)內(nèi)的代碼。
某種意義上,這個(gè)缺點(diǎn)是致命的。不推薦使用。
總結(jié)
用原型鏈的方式實(shí)現(xiàn)一個(gè)JS繼承,其實(shí)就是希望構(gòu)造函數(shù)Son創(chuàng)建出來(lái)的對(duì)象son,它的原型鏈上加上父類Ptotype,所以最后就是要修改Stotype的[[prototype]]。
鑒于性能、兼容性、副作用等考慮,推薦使用方法1,即通過(guò)Object.create(Ptotype)創(chuàng)建一個(gè)指定了[[prototype]]的新對(duì)象,替換掉原來(lái)的Stotype指向的對(duì)象。
總結(jié)幾個(gè)核心知識(shí)點(diǎn):
任何對(duì)象都有[[prototype]]屬性,讀寫對(duì)象屬性發(fā)現(xiàn)當(dāng)前對(duì)象不存在時(shí),會(huì)訪問(wèn)[[prototype]]指向的對(duì)象嘗試訪問(wèn)屬性,于是原型鏈形成了。函數(shù)創(chuàng)建時(shí),它的prototype屬性會(huì)拿到一個(gè)原型對(duì)象。當(dāng)函
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 足浴布草清洗合同協(xié)議
- 滿贈(zèng)活動(dòng)協(xié)議書
- 烤鴨投放協(xié)議書
- 正規(guī)交房協(xié)議書
- 勞務(wù)派遣加盟合同書
- 商業(yè)門面買賣合同
- 委托限時(shí)代賣合同
- 退伙分期協(xié)議書范本
- 轉(zhuǎn)讓文章版權(quán)協(xié)議書范本
- 通風(fēng)系統(tǒng)維保合同協(xié)議
- DL/T 5182-2021 火力發(fā)電廠儀表與控制就地設(shè)備安裝、管路、電纜設(shè)計(jì)規(guī)程
- 麟龍量能飽和度圓圈指標(biāo)
- 失信被執(zhí)行人生活費(fèi)申請(qǐng)書
- 成立應(yīng)急救援預(yù)案編制小組范文
- 2023年高考地理(山東卷)真題評(píng)析
- 第三帝國(guó)三部曲:當(dāng)權(quán)的第三帝國(guó)(全集)
- 全國(guó)城市一覽表-excel
- 《成年人的世界沒(méi)有容易二字》讀書筆記
- 《違規(guī)違紀(jì)典型案例警示錄》心得體會(huì)總結(jié)
- 國(guó)際金融課后習(xí)題答案(吳志明第五版)第1-9章
- 口腔器械消毒滅菌技術(shù)規(guī)范
評(píng)論
0/150
提交評(píng)論