Javascript 對原型鏈的理解文章

最近在解讀React源碼的時(shí)候,在讀到以下代碼的時(shí)候

Component.prototype.setState = function (partialState, callback) {

? ...

};

var pureComponentPrototype = PureComponent.prototype = new ComponentDummy();

pureComponentPrototype.constructor = PureComponent;

發(fā)現(xiàn)對于js對象中的原型理解不夠深入的話,無法繼續(xù)往下讀源碼。以前對于這一塊似懂非懂,由于工作中運(yùn)用得很少就把它放到一旁?,F(xiàn)在為了能完全理解React源碼,就重新復(fù)習(xí)了下,做到了理解以后再把腦海中的知識(shí)寫下來加深印象,如果接下來的話哪里不對,請大家指出,我會(huì)及時(shí)改正,愿大家在學(xué)習(xí)的路上越挫越勇。

首先,我們用到常常用到的一句話,世界萬物皆對象。所以在Javascript中,每一個(gè)函數(shù)實(shí)際上都是一個(gè)函數(shù)對象。

我之所以先提這么一句,是因?yàn)楹瘮?shù)(Function)和對象(Object)是我們理解原型繞不過的坎,為了怕讀者混淆,函數(shù)我們會(huì)統(tǒng)一稱呼為函數(shù)對象,對象即對象。

我們先聊構(gòu)成,再聊實(shí)際作用。

首先,每一個(gè)函數(shù)對象都有一個(gè)prototype屬性,該屬性指向原型對象,且原型對象會(huì)自動(dòng)生成一個(gè)名叫constructor屬性。

然后,每一個(gè)對象都有一個(gè)[[prototype]]對象,這是JS的一個(gè)官方非標(biāo)準(zhǔn)定義,在瀏覽器中或者各種調(diào)試臺(tái)中,我們可以看到的實(shí)際體現(xiàn)是? someObject.__proto__,這是因?yàn)闉g覽器對該屬性的一種實(shí)現(xiàn),如果瀏覽器無法打印該屬性只能說明該瀏覽器對這個(gè)屬性沒有做兼容,你可以理解為 someObject.[[prototype]] === someObject.__proto__。


我創(chuàng)建并打印一個(gè)example函數(shù)對象,他的構(gòu)造如下:

函數(shù)對象構(gòu)造

我們可以清楚的看到該函數(shù)對象包含prototype屬性,該屬性中含有constructor屬性,也有chrome瀏覽器對[[prototype]]屬性的實(shí)現(xiàn),即__proto__屬性。而prototype中也包含__proto__屬性,每一個(gè)對象都有一個(gè)[[prototype]]對象。

而既然每個(gè)對象都有這個(gè)屬性且瀏覽器大費(fèi)周章實(shí)現(xiàn)這個(gè)屬性,這個(gè)對象指向哪里呢?

該對象指向該對象的構(gòu)造函數(shù)的原型對象,這句話有點(diǎn)繞,我們來分析一下。

首先,那么怎么來理解構(gòu)造對象,構(gòu)造函數(shù)就是你創(chuàng)建新對象所使用的磨具,如下圖:


構(gòu)造函數(shù)

在這里,Mike對象是我們使用Person函數(shù)為磨具構(gòu)造出來的,那Person函數(shù)就是Mike對象的構(gòu)造函數(shù)。

那么根據(jù)我們上面的話,那么就能得出如下的公式,即

Mike.__proto__ === Person.prototype

那么又有人會(huì)問,我知道了__proto__的指向,那么prototype又該向哪里呢?

先簡單的回答下,該屬性指向原型對象。

回歸正題,什么是原型鏈,且為什么要有原型對象?

我們來看如下的例子:


理解原型對象


首先,我們使用Person構(gòu)造函數(shù)創(chuàng)建了Mike和John對象,并為他們賦值,我們可以發(fā)現(xiàn),不管是name屬性,age屬性還是array屬性他們都是獨(dú)自儲(chǔ)存,說明它們雖然都拷貝了構(gòu)造函數(shù)的靜態(tài)屬性,但是他們是分別儲(chǔ)存,那么對于屬性還好,那么如果我想和其他同一個(gè)構(gòu)造函數(shù)出來的對象共用一個(gè)方法,或者繼承一個(gè)方法該咋辦呢?


原型屬性


那么我們就為Person對象函數(shù)的原型上添加一個(gè)share屬性,讓其指向一個(gè)數(shù)組。

由于是在原型鏈上添加了該屬性,那么當(dāng)我們?nèi)ナ褂肕ike.share時(shí),js會(huì)去尋找Mike身上存不存在share對象,如果Mike上不存在,那么就會(huì)去Mike的__proto__上找(我們知道對象的[[prototype]]指向了構(gòu)造函數(shù)的原型對象),然后就會(huì)在Person的prototype屬性身上找到該屬性(如果構(gòu)造對象身上找不到該屬性,就會(huì)繼續(xù)往上找,直到Object.prototype,如果Object身上沒有該方法,就會(huì)報(bào)錯(cuò))。我們現(xiàn)在發(fā)現(xiàn),我們使兩個(gè)實(shí)例對象都共用了某一個(gè)屬性或者某一個(gè)方法。所以,我們會(huì)說靜態(tài)方法,實(shí)例方法等等是實(shí)現(xiàn)了對象的多態(tài),而原型對象實(shí)現(xiàn)了代碼的繼承。


好了,我繼續(xù)挖React源碼了,goodbye~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容