亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

淺談JS原型鏈

系統(tǒng) 1879 0

淺談JS原型鏈

原型鏈

ECMAScript中描述了原型鏈的概念。我們知道ECMAScript并不像C++,Java那樣使用類,但是對(duì)象仍然可以通過(guò)多種方式創(chuàng)建,其中就有構(gòu)造函數(shù)方式。每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,同時(shí)都有一個(gè)prototype屬性, prototype屬性指向構(gòu)造函數(shù)的原型對(duì)象,它被用來(lái)實(shí)現(xiàn)基于原型的繼承和共享。而原型對(duì)象又都默認(rèn)會(huì)取得一個(gè)constructor屬性,這個(gè)屬性包含一個(gè)指向構(gòu)造函數(shù)(prototype屬性所在函數(shù))的指針。每個(gè)通過(guò)調(diào)用構(gòu)造函數(shù)創(chuàng)建的實(shí)例對(duì)象都擁有一個(gè)指向原型對(duì)象的指針,ECMA-262第5版中叫這個(gè)指針為[[prototype]],雖然在腳本上沒(méi)有標(biāo)準(zhǔn)的方式訪問(wèn)[[prototype]],但Chrome、Firefox和Safari在每個(gè)對(duì)象上都支持一個(gè)屬性_proto_,而在其他實(shí)現(xiàn)中,這個(gè)屬性對(duì)腳本是完全不可見(jiàn)的。假如原型對(duì)象等于另一個(gè)類型的實(shí)例,那么它就擁有指向創(chuàng)建該實(shí)例的構(gòu)造函數(shù)的原型對(duì)象的指針,依此類推,就形成了一條指針鏈,這就是原型鏈的概念。通過(guò)下面的圖形我們可以更清晰地了解原型鏈的概念。

ECMA5中可以使用Object.getPrototypeOf()來(lái)獲取實(shí)例的構(gòu)造函數(shù)的prototype

淺談JS原型鏈

事實(shí)上,上圖所展示的原型鏈還少一環(huán)。我們知道,所有引用類型默認(rèn)都繼承了Object,而這個(gè)繼承也是通過(guò)原型鏈實(shí)現(xiàn)的。函數(shù)是可調(diào)用的對(duì)象,所有函數(shù)的默認(rèn)原型對(duì)象都是Object的實(shí)例,所以函數(shù)的原型對(duì)象都會(huì)包含一個(gè)指向Object構(gòu)造函數(shù)的原型對(duì)象的指針,也即指向Object.prototype的指針[[prototype]]。這樣就解釋了為什么所有自定義對(duì)象類型都會(huì)繼承toLocaleString()、toString()等Object原型對(duì)象的默認(rèn)方法了。還是來(lái)上圖吧。

淺談JS原型鏈

當(dāng)然,還有很重要的一點(diǎn)是我們需要注意的:對(duì)象實(shí)例中的指針[[prototype]]只指向原型對(duì)象,并不指向構(gòu)造函數(shù)。

原型語(yǔ)法

通常,我們可以用一個(gè)包含所有屬性和方法的對(duì)象字面量來(lái)重寫(xiě)整個(gè)原型對(duì)象。例如

1 function Person(){}
2 Person.prototype = {
3 ?? name: "bella" ,
4 ?? age: 21,
5 ?? sayHello: function (){
6 ???? alert( this .name);
7 ?? }
8 }

不過(guò),我們需要注意的是,重寫(xiě)之后,構(gòu)造函數(shù)Person的原型對(duì)象的constructor屬性不再指向Person了,因?yàn)樵撜Z(yǔ)法的本質(zhì)是完全重寫(xiě)了默認(rèn)的原型對(duì)象,所以constructor屬性也就變成了新對(duì)象的constructor屬性,指向Object構(gòu)造函數(shù),我們此時(shí)就不能通過(guò)constuctor來(lái)確定對(duì)象的類型了。

可以通過(guò)Person.prototype.constructor = Person恢復(fù)constructor的指針。

原型的動(dòng)態(tài)性

原型在查找值的過(guò)程中是一次搜索,當(dāng)我們想引用一個(gè)對(duì)象的某個(gè)屬性時(shí),所引用到的是原型鏈中包含該屬性名的第一個(gè)對(duì)象所對(duì)應(yīng)的屬性值。換句話說(shuō),直接引用這個(gè)屬性的對(duì)象會(huì)首先被查詢是否包含該屬性名,如果包含,該屬性值就是我們想獲取的,查詢停止,如果不包含,會(huì)接著查詢?cè)搶?duì)象的原型是否包含該屬性,依此類推。

我們可以隨時(shí)動(dòng)態(tài)地為原型添加屬性和方法,而且,基于這種搜索過(guò)程,我們對(duì)原型對(duì)象所做的任何修改都能立即從對(duì)象實(shí)例上看到,即使該修改是在創(chuàng)建實(shí)例之后。但如果是用上面提到的語(yǔ)法重寫(xiě)整個(gè)原型對(duì)象就另當(dāng)別論了。因?yàn)橹貙?xiě)原型對(duì)象會(huì)切斷現(xiàn)有原型對(duì)象與原來(lái)已經(jīng)存在的任何對(duì)象實(shí)例之間的聯(lián)系,它們包含的指針[[prototype]]仍然指向原來(lái)的原型對(duì)象,我們可以看看下面的小例子。

01 function Person(){}
02 var person1 = new Person();
03 Person.prototype = {
04 ?? name: "bella" ,
05 ?? age: 21,
06 ?? sayHello: function (){
07 ???? alert( this .name);
08 ?? }
09 }
10 person1.sayHello();? //error

上面的例子中,我們先創(chuàng)建了Person的一個(gè)實(shí)例對(duì)象person1,然后重寫(xiě)了Person的原型對(duì)象,之后再調(diào)用person1.sayHello()就會(huì)發(fā)生錯(cuò)誤。因?yàn)閜erson1中包含的指針[[prototype]]仍然指向原來(lái)的原型對(duì)象,并不包含新的原型對(duì)象中定義的sayHello屬性。

原型的問(wèn)題

原型模式使得所有對(duì)象實(shí)例在默認(rèn)情況下取得相同的屬性值,對(duì)于屬性值為函數(shù)的情況,這正是我們希望看到的,所有對(duì)象實(shí)例共享這一函數(shù)而不需要重復(fù)定義,但是對(duì)于屬性值為基本值的情況,我們通常希望不同的對(duì)象實(shí)例擁有不同的基本值,不過(guò),我們可以通過(guò)在對(duì)象實(shí)例上添加同名屬性來(lái)隱藏原型對(duì)象中的屬性。但是,如果包含引用類型值的屬性,問(wèn)題就顯現(xiàn)出來(lái)了。

01 function Person(){}
02 Person.prototype = {
03 ?? name: "bella" ,
04 ?? age: 21,
05 ?? classmates: [ "Lucy" , "Lily" ],
06 ?? sayHello: function (){
07 ???? alert( this .name);
08 ?? }
09 }
10 var person1 = new Person();
11 var person2 = new Person();
12 person1.classmates.push( "Mark" );
13 alert(person1.classmates === person2.classmates);? //true

這里,我們?yōu)镻erson.prototype對(duì)象添加了classmates屬性,值為一個(gè)字符串?dāng)?shù)組,然后創(chuàng)建了兩個(gè)對(duì)象實(shí)例person1, person2。由于person1, person2所擁有的classmates屬性其實(shí)是共享原型對(duì)象Person.prototype的classmates屬性得到的,也就是數(shù)組只存在于Person.prototype對(duì)象中,person1和person2引用的是同一個(gè)數(shù)組,對(duì)person1中classmates的修改也會(huì)從person2.classmates中反映出來(lái),這樣會(huì)導(dǎo)致所有對(duì)象實(shí)例共享一個(gè)數(shù)組,這往往不是我們想要的。

以上,我只是簡(jiǎn)單地分析了原型鏈的概念和原型對(duì)象的基本特性,希望能對(duì)大家有小小的幫助,想要更深刻地認(rèn)識(shí)它,當(dāng)然還是得靠大家在實(shí)際項(xiàng)目中去學(xué)習(xí)和體會(huì)。

?

參考資料:Standard ECMA-262,JavaScript高級(jí)程序設(shè)計(jì)。

淺談JS原型鏈


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国内自拍青青草 | 国内精品不卡一区二区三区 | 91天堂97年嫩模在线观看 | 欧美日韩在大午夜爽爽影院 | 欧美激情欧美狂野欧美精品免费 | 男人都懂www深夜免费网站 | 亚洲一区中文字幕 | 国产精品精品 | 国产亚洲欧美在在线人成 | 欧美综合视频在线 | 国产伦精品一区二区三区四区 | 久久精品这里是免费国产 | 久热中文字幕在线观看 | 亚洲综合区小说区激情区噜噜 | www夜夜操com | 99国产精品视频久久久久 | 中文精品久久久久国产不卡 | 久久精品五月天 | 操日日 | 久久这里只精品国产99热 | 国内精品视频一区二区八戒 | 2021久久精品国产99国产 | 91日本在线精品高清观看 | 中文字幕一区日韩在线视频 | 伊人五月在线 | 天天干一干 | 国产精品福利久久香蕉中文 | 欧美一区二区手机在线观看视频 | 国产午夜不卡在线观看视频666 | 国产精品福利视频 | 欧美久久xxxxxx影院 | 国产一级做a爱片久久毛片a | 国产极品白嫩美女在线观看看 | 天天干一干 | 四虎在线视频观看大全影视 | 四虎国产欧美成人影院 | 97国内免费久久久久久久久久 | 日韩欧美中文字幕在线观看 | 欧美精品日本一级特黄 | 干美女网站 | 日日日日操 |