24:JS 原型鏈,原型鏈的頂端是什么?Object 的原型是什么?Object 的原型的 原型是什么?在數(shù)組原型鏈上實(shí)現(xiàn)刪除數(shù)組重復(fù)數(shù)據(jù)的方法

能夠把這個(gè)講清楚弄明白是一件很困難的事,

首先明白原型是什么,在 ES6 之前,JS 沒有類和繼承的概念,JS 是通過原型來實(shí)現(xiàn)繼承的,在 JS 中一個(gè)構(gòu)造函數(shù)默認(rèn)帶有一個(gè) prototype 屬性,這個(gè)的屬性值是一個(gè)對象,同時(shí)這個(gè) prototype 對象自帶有一個(gè) constructor 屬性,這個(gè)屬性指向這個(gè)構(gòu)造函數(shù),同時(shí)每一個(gè)實(shí)例都會有一個(gè)proto屬性指向這個(gè) prototype 對象,我們可以把這個(gè)叫做隱式原型,我們在使用一個(gè)實(shí)例的方法的時(shí)候,會先檢查這個(gè)實(shí)例中是否有這個(gè)方法,沒有的話就會檢查這個(gè) prototype 對象是否有這個(gè)方法,基于這個(gè)規(guī)則,如果讓原型對象指向另一個(gè)類型的實(shí)例,即

constructor1.protoytpe=instance2,這時(shí)候如果試圖引用 constructor1 構(gòu)造的實(shí)例 instance1 的某個(gè)屬性 p1,

首先會在 instance1 內(nèi)部屬性中找一遍,

接著會在 instance1.proto(constructor1.prototype)即是 instance2 中尋找 p1

搜尋軌跡:instance1 -> instance2 -> constructor2.prototype……->Object.prototype;這即是原型鏈,原型鏈頂端是 Object.prototype

補(bǔ)充學(xué)習(xí):

每個(gè)函數(shù)都有一個(gè) prototype 屬性,這個(gè)屬性指向了一個(gè)對象,這個(gè)對象正是調(diào)用該函數(shù)而創(chuàng)建的實(shí)例的原型,那么什么是原型呢,可以這樣理解,每一個(gè) JavaScript 對象在創(chuàng)建的時(shí)候就會預(yù)制管理另一個(gè)對象,這個(gè)對象就是我們所說的原型,每一個(gè)對象都會從原型繼承屬性,如圖:

prototype01.jpg

那么怎么表示實(shí)例與實(shí)例原型的關(guān)系呢,這時(shí)候就要用到第二個(gè)屬性 proto

這是每一個(gè) JS 對象都會有的一個(gè)屬性,指向這個(gè)對象的原型,如圖:

prototype02.jpg

既然實(shí)例對象和構(gòu)造函數(shù)都可以指向原型,那么原型是否有屬性指向構(gòu)造函數(shù)或者實(shí)例呢,指向?qū)嵗菦]有的,因?yàn)橐粋€(gè)構(gòu)造函數(shù)可以生成多個(gè)實(shí)例,但是原型有屬性可以直接指向構(gòu)造函數(shù),通過 constructor 即可

接下來講解實(shí)例和原型的關(guān)系:

當(dāng)讀取實(shí)例的屬性時(shí),如果找不到,就會查找與對象相關(guān)的原型中的屬性,如果還查不到,就去找原型的原型,一直找到最頂層,那么原型的原型是什么呢,首先,原型也是一個(gè)對象,既然是對象,我們就可以通過構(gòu)造函數(shù)的方式創(chuàng)建它,所以原型對象就是通過 Object 構(gòu)造函數(shù)生成的,如圖:

prototype03.jpg

那么 Object.prototype 的原型呢,我們可以打印 console.log(Object.prototype.proto === null),返回 true

null 表示沒有對象,即該處不應(yīng)有值,所以 Object.prototype 沒有原型,如圖:

prototype04.jpg

圖中這條藍(lán)色的線即是原型鏈,

最后補(bǔ)充三點(diǎn):

constructor:

function Person(){

}

var person = new Person();

console.log(Person === person.constructor);

原本 person 中沒有 constructor 屬性,當(dāng)不能讀取到 constructor 屬性時(shí),會從 person 的原型中讀取,所以指向構(gòu)造函數(shù) Person

proto

絕大部分瀏覽器支持這個(gè)非標(biāo)準(zhǔn)的方法訪問原型,然而它并不存在與 Person.prototype 中,實(shí)際上它來自 Object.prototype,當(dāng)使用 obj.proto時(shí),可以理解為返回來

Object.getPrototype(obj)

繼承:

前面說到,每個(gè)對象都會從原型繼承屬性,但是引用《你不知道的 JS》中的話,繼承意味著復(fù)制操作,然而 JS 默認(rèn)不會復(fù)制對象的屬性,相反,JS 只是在兩個(gè)對象之間創(chuàng)建一個(gè)關(guān)聯(lián),這樣子一個(gè)對象就可以通過委托訪問另一個(gè)對象的屬性和函數(shù),所以與其叫繼承,叫委托更合適。

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

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

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