一篇文章看懂_proto_和prototype的關(guān)系及區(qū)別

原型是javascript面向?qū)ο缶幊讨蟹浅V匾母拍睿也⒉皇悄敲慈菀锥E既豢吹揭粋€題目:闡述proto和prototype的關(guān)系。看到這個問題的時候,我的腦海浮現(xiàn)出一些概念,但卻說不出來。先來看一張圖

image.png

如果能看懂圖中的關(guān)系基本上就可以解釋出*proto*prototype的關(guān)系和區(qū)別了

所以接下來一一介紹圖中的一些概念

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

使用構(gòu)造函數(shù)創(chuàng)建對象


image.png

Person就是一個構(gòu)造函數(shù),通過new創(chuàng)建了person1對象實例

其實構(gòu)造函數(shù)就和普通函數(shù)沒有多大區(qū)別,首字母大寫只是約定俗成,不大寫照樣可以。關(guān)鍵是調(diào)用它的方式——通過new,那么這里又會牽扯到另一個問題,使用new調(diào)用后會內(nèi)部會執(zhí)行哪些操作

prototype

圖中可以看到在Person構(gòu)造函數(shù)下有一個prototype屬性。


image.png

這個并不是構(gòu)造函數(shù)專有,每個函數(shù)都會有一個prototype屬性,這個屬性是一個指針,指向一個對象,記住只有函數(shù)才有,并且通過bind()綁定的也沒有。


image.png

前面所說prototype屬性指向一個對象,那么這個對象是什么?

根據(jù)第一張圖片可以清晰看到,prototype指向Person.prototype。沒錯Person.prototype就是原型對象,也就是實例person1和person2的原型。

原型對象的好處是可以讓所有對象實例共享它所包含的屬性和方法

所以構(gòu)造函數(shù)和原型之間的關(guān)系為


image.png

proto
第一張圖中看到,在person1和person2實例對象下面有一個[[prototype]],其實沒有標準的方式可以訪問它,但是主流瀏覽器上在每個對象上(null除外)都支持一個屬性,那就是proto,這個屬性會指向該對象的原型


image.png

image.png

所以總結(jié)可得proto就是用來將對象與該對象的原型相連

在所有實現(xiàn)中都無法訪問到[[prototype]],但是可以通過一些方法來確定對象之間時候存在這種關(guān)系

instanceof,這個操作符只能處理對象(person1)和函數(shù)(帶.prototype引用的Person)之間的關(guān)系

person1 instanceof Person // true

isPrototypeOf,如果[[prototype]]指向調(diào)用此方法的對象,那么這個方法就會返回true

Person.prototype.isPrototypeOf(person1) // true
Person.prototype.isPrototypeOf(person2) // true

Object.getPrototypeOf這個方法返回[[Prototype]]的值,可以獲取到一個對象的原型

Object.getPrototypeOf(person1) === Person.prototype // true
constuctor
我們來繼續(xù)理解第一張圖中的關(guān)系,現(xiàn)在理解原型對象(PErson.prototype)下constructor屬性

這個屬性其實就是將原型對象指向關(guān)聯(lián)的構(gòu)造函數(shù)


image.png

再來看一些代碼


image.png

那豈不是實例person1也有.constructor屬性,其實沒有,通過原型鏈在原型Person.prtototype上面找到的

理順了這層關(guān)系,第一張圖就全部理解完了,是不是差不多就可以解釋出proto和prototype的關(guān)系和區(qū)別呢

原型鏈
我們既然探索完了他們的關(guān)系,那我們來繼續(xù)探索一下原型和原型鏈的奧秘所在,其實原型鏈就是依托proto和prototype連接起來的

在探索之前我們先來理解一下實例屬性和原型屬性的關(guān)系,見代碼


image.png

上面代碼中在實例屬性和原型屬性都有一個名為name的屬性,但是最后輸出來的是實例屬性上的值

當我們讀取一個屬性的時候,如果在實例屬性上找到了,就讀取它,不會管原型屬性上是否還有相同的屬性,這其實就是屬性屏蔽。即當實例屬性和原型屬性擁有相同名字的時候,實例屬性會屏蔽原型屬性,記住只是屏蔽,不會修改,原型屬性那個值還在

但是如果在實例屬性上沒有找到的話,就會在實例的原型上去找,如果原型上還沒有,就繼續(xù)到原型的原型上去找,直到盡頭,這個盡頭是啥?不急,等會說


image.png

上面代碼中person1實例并沒有name屬性,但仍然可以輸出值,就是在原型上找到的
如何檢測一個屬性存在于實例中,還是原型中?
使用方法hasOwnProperty,屬性只有存在于實例中才會返回true


image.png

既然講到了方法,就再補充一些方法

in操作符

前面提到hasOwnProperty方法可用于檢測屬性是否是實例屬性,in則會遍歷所有屬性,不管是實例上的,還是原型上的

in操作符有兩種使用方式,單獨使用和在for-in循環(huán)中使用,先上基礎(chǔ)代碼


image.png

單獨使用


image.png

Object.keys() 此方法可以獲取對象的所有可枚舉的屬性的名字
var keys = Object.keys(person1)

console.log(keys) // ["name"]

var keys = Object.keys(Person.prototype)
console.log(keys) // ["age"]

好了方法講完了,繼續(xù),假如在原型對象Person.prototype還是沒有找到這個屬性,會停止嗎?前面已經(jīng)說了,還會繼續(xù)找,這并不是盡頭。原型對象也是對象,所以它也有proto屬性,連接它的原型,原型對象Person.prototype的原型就是Object.prototype這個大boss,所有原型對象都是Object構(gòu)造函數(shù)生成的

正是因為所有的原型最終都會指向Object.prototype,所以對象的很多方法其實都是繼承于此,比如toString()、valueOf(),前面用到的hasOwnProperty,甚至是.constructor、proto

Object.prototype有原型嗎?


image.png

沒有,為null,所以它就是前面所提到的盡頭

總結(jié)成一張圖


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

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

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