詳解JavaScript中的原型和原型鏈
原型鏈圖
原型必備知識(shí)
要了解原型就必須搞清三個(gè)屬性:__proto__
、prototype
、 constructor
。
1.__proto__、 constructor屬性是對(duì)象所獨(dú)有的;
2.prototype屬性是函數(shù)獨(dú)有的;
3.js中函數(shù)也是對(duì)象的一種,那么函數(shù)同樣也有屬性__proto__、 constructor;
原型五大規(guī)則:
1.所有引用類(lèi)型(對(duì)象,數(shù)組,函數(shù))都具有對(duì)象特性,即可以自由擴(kuò)展屬性
2.所有引用類(lèi)型(對(duì)象,數(shù)組,函數(shù))都具有一個(gè)__proto__(隱式原型)屬性,是一個(gè)普通對(duì)象
3.所有的函數(shù)都具有prototype(顯式原型)屬性,也是一個(gè)普通對(duì)象
4.所有引用類(lèi)型(對(duì)象,數(shù)組,函數(shù))__proto__值指向它構(gòu)造函數(shù)的prototype
5.當(dāng)試圖得到一個(gè)對(duì)象的屬性時(shí),如果變量本身沒(méi)有這個(gè)屬性,則會(huì)去他的__proto__中去找
prototype屬性(顯示原型)
首先創(chuàng)建一個(gè)構(gòu)造函數(shù)
var Parent = function(){ } //定義一個(gè)函數(shù),那它只是一個(gè)普通的函數(shù) var p1 = new Parent(); //通過(guò)關(guān)鍵字new,Parent成為構(gòu)造函數(shù) //創(chuàng)建了一個(gè)Parent構(gòu)造函數(shù)的實(shí)例 p1
prototype
是函數(shù)獨(dú)有的屬性,通過(guò)這個(gè)屬性就能訪問(wèn)到原型;
prototype
設(shè)計(jì)之初就是為了實(shí)現(xiàn)繼承,讓由特定函數(shù)創(chuàng)建的所有實(shí)例共享屬性和方法,也可以說(shuō)是讓某一個(gè)構(gòu)造函數(shù)實(shí)例化的所有對(duì)象可以找到公共的方法和屬性。有了prototype
我們不需要為每一個(gè)實(shí)例創(chuàng)建重復(fù)的屬性方法,而是將屬性方法創(chuàng)建在構(gòu)造函數(shù)的原型對(duì)象上(prototype)。那些不需要共享的才創(chuàng)建在構(gòu)造函數(shù)中。
Parent是構(gòu)造函數(shù),Parent.prototype就是原型
Parent.prototype
上添加的屬性和方法叫做原型屬性和原型方法,該構(gòu)造函數(shù)的實(shí)例都可以訪問(wèn)調(diào)用。
proto屬性(隱式原型)
__proto__屬性是對(duì)象(包括函數(shù))獨(dú)有的。
每個(gè)對(duì)象都有__proto__屬性,該屬性指向的就是該對(duì)象的原型對(duì)象。
p1.__proto__ === Parent.prototype; // true
__proto__通常稱(chēng)為隱式原型,prototype通常稱(chēng)為顯式原型,可以說(shuō)一個(gè)對(duì)象的隱式原型指向了該對(duì)象的構(gòu)造函數(shù)的顯式原型。那么在顯式原型上定義的屬性方法,通過(guò)隱式原型傳遞給了構(gòu)造函數(shù)的實(shí)例。這樣一來(lái)實(shí)例就能很容易的訪問(wèn)到構(gòu)造函數(shù)原型上的方法和屬性了。
Parent.prototype
的隱式原型指向了對(duì)象原型
Parent.prototype.__proto__ === Object.prototype; //true
這里引出原型鏈的概念,當(dāng)調(diào)用p1.toString()
的時(shí)候,先在p1對(duì)象本身尋找,沒(méi)有找到則通過(guò)p1.__proto__找到了原型對(duì)象Parent.prototype
,也沒(méi)有找到,又通過(guò)Parent.prototype.__proto__
找到了上一層原型對(duì)象Object.prototype。在這一層找到了toString方法。返回該方法供p1使用。
當(dāng)然如果找到Object.prototype上也沒(méi)找到,就在Object.prototype.__proto__
中尋找,但是Object.prototype.__proto__ === null
所以就返回undefined。這就是為什么當(dāng)訪問(wèn)對(duì)象中一個(gè)不存在的屬性時(shí),返回undefined了。
constructor屬性
既然構(gòu)造函數(shù)通過(guò) prototype 來(lái)訪問(wèn)到原型,那么原型也應(yīng)該能夠通過(guò)某種途徑訪問(wèn)到構(gòu)造函數(shù),這就是 constructor。
如前面的例子p1就是一個(gè)對(duì)象,那p1的構(gòu)造函數(shù)就是Parent()。Parent的構(gòu)造函數(shù)是Function()
p1.constructor => f Parent{} Parent.construtor => f Function() { [native code] } Function.constructor => ? Function() { [native code] }
Function是所有函數(shù)的根構(gòu)造函數(shù)。
通過(guò)例子可以看到,p1的constructor
屬性指向了Parent,那么Parent就是p1的構(gòu)造函數(shù)。同樣Parent的constructor屬性指向了Function,那么Function就是Parent的構(gòu)造函數(shù),然后又驗(yàn)證了Function就是根構(gòu)造函數(shù)。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
JavaScript設(shè)計(jì)模式之原型模式詳情
這篇文章主要介紹了JavaScript設(shè)計(jì)模式之原型模式詳情,原型的這種設(shè)計(jì)模式,是一種比較簡(jiǎn)單的設(shè)計(jì)模式,由于初始化都做一些重復(fù)性的東西,造成的性能消2022-06-06基于BootStrap的Metronic框架實(shí)現(xiàn)頁(yè)面鏈接收藏夾功能按鈕移動(dòng)收藏記錄(使用Sortable進(jìn)行拖動(dòng)排序)
這篇文章主要介紹了基于BootStrap的Metronic框架實(shí)現(xiàn)頁(yè)面鏈接收藏夾功能按鈕移動(dòng)收藏記錄(使用Sortable進(jìn)行拖動(dòng)排序)的相關(guān)資料,非常不錯(cuò),需要的朋友可以參考下2016-08-08微信小程序?qū)崿F(xiàn)答題倒計(jì)時(shí)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)答題倒計(jì)時(shí),自定義計(jì)時(shí)器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09layui table checked獲取選中數(shù)據(jù)方式
這篇文章主要介紹了layui table checked獲取選中數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10實(shí)例學(xué)習(xí)Javascript之構(gòu)建方法、屬性
實(shí)例學(xué)習(xí)Javascript之構(gòu)建方法、屬性...2007-03-03javascript 操作Word和Excel的實(shí)現(xiàn)代碼
javascript 操作Word和Excel的實(shí)現(xiàn)代碼, 需要的朋友可以參考下。2009-10-10js創(chuàng)建數(shù)組的簡(jiǎn)單方法
下面小編就為大家?guī)?lái)一篇JS創(chuàng)建數(shù)組的簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07