詳解JavaScript中的原型和原型鏈
原型鏈圖

原型必備知識
要了解原型就必須搞清三個屬性:__proto__、prototype、 constructor。
1.__proto__、 constructor屬性是對象所獨(dú)有的;
2.prototype屬性是函數(shù)獨(dú)有的;
3.js中函數(shù)也是對象的一種,那么函數(shù)同樣也有屬性__proto__、 constructor;
原型五大規(guī)則:
1.所有引用類型(對象,數(shù)組,函數(shù))都具有對象特性,即可以自由擴(kuò)展屬性
2.所有引用類型(對象,數(shù)組,函數(shù))都具有一個__proto__(隱式原型)屬性,是一個普通對象
3.所有的函數(shù)都具有prototype(顯式原型)屬性,也是一個普通對象
4.所有引用類型(對象,數(shù)組,函數(shù))__proto__值指向它構(gòu)造函數(shù)的prototype
5.當(dāng)試圖得到一個對象的屬性時,如果變量本身沒有這個屬性,則會去他的__proto__中去找
prototype屬性(顯示原型)
首先創(chuàng)建一個構(gòu)造函數(shù)
var Parent = function(){
}
//定義一個函數(shù),那它只是一個普通的函數(shù)
var p1 = new Parent();
//通過關(guān)鍵字new,Parent成為構(gòu)造函數(shù)
//創(chuàng)建了一個Parent構(gòu)造函數(shù)的實(shí)例 p1
prototype是函數(shù)獨(dú)有的屬性,通過這個屬性就能訪問到原型;
prototype設(shè)計(jì)之初就是為了實(shí)現(xiàn)繼承,讓由特定函數(shù)創(chuàng)建的所有實(shí)例共享屬性和方法,也可以說是讓某一個構(gòu)造函數(shù)實(shí)例化的所有對象可以找到公共的方法和屬性。有了prototype我們不需要為每一個實(shí)例創(chuàng)建重復(fù)的屬性方法,而是將屬性方法創(chuàng)建在構(gòu)造函數(shù)的原型對象上(prototype)。那些不需要共享的才創(chuàng)建在構(gòu)造函數(shù)中。
Parent是構(gòu)造函數(shù),Parent.prototype就是原型

Parent.prototype上添加的屬性和方法叫做原型屬性和原型方法,該構(gòu)造函數(shù)的實(shí)例都可以訪問調(diào)用。
proto屬性(隱式原型)
__proto__屬性是對象(包括函數(shù))獨(dú)有的。
每個對象都有__proto__屬性,該屬性指向的就是該對象的原型對象。
p1.__proto__ === Parent.prototype; // true
__proto__通常稱為隱式原型,prototype通常稱為顯式原型,可以說一個對象的隱式原型指向了該對象的構(gòu)造函數(shù)的顯式原型。那么在顯式原型上定義的屬性方法,通過隱式原型傳遞給了構(gòu)造函數(shù)的實(shí)例。這樣一來實(shí)例就能很容易的訪問到構(gòu)造函數(shù)原型上的方法和屬性了。
Parent.prototype的隱式原型指向了對象原型
Parent.prototype.__proto__ === Object.prototype; //true

這里引出原型鏈的概念,當(dāng)調(diào)用p1.toString()的時候,先在p1對象本身尋找,沒有找到則通過p1.__proto__找到了原型對象Parent.prototype,也沒有找到,又通過Parent.prototype.__proto__找到了上一層原型對象Object.prototype。在這一層找到了toString方法。返回該方法供p1使用。
當(dāng)然如果找到Object.prototype上也沒找到,就在Object.prototype.__proto__中尋找,但是Object.prototype.__proto__ === null所以就返回undefined。這就是為什么當(dāng)訪問對象中一個不存在的屬性時,返回undefined了。
constructor屬性
既然構(gòu)造函數(shù)通過 prototype 來訪問到原型,那么原型也應(yīng)該能夠通過某種途徑訪問到構(gòu)造函數(shù),這就是 constructor。
如前面的例子p1就是一個對象,那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ù)。
通過例子可以看到,p1的constructor屬性指向了Parent,那么Parent就是p1的構(gòu)造函數(shù)。同樣Parent的constructor屬性指向了Function,那么Function就是Parent的構(gòu)造函數(shù),然后又驗(yàn)證了Function就是根構(gòu)造函數(shù)。

總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
基于JavaScript 實(shí)現(xiàn)拖放功能
本文通過實(shí)例代碼給大家介紹了JavaScript 實(shí)現(xiàn)拖放功能,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-09
獲取本機(jī)IP地址的實(shí)例(JavaScript / Node.js)
下面小編就為大家分享一篇使用JavaScript和Node.js獲取本機(jī)IP地址的實(shí)例,具有很好的參考價值,希望對大家有所幫助2017-11-11
30分鐘快速入門掌握ES6/ES2015的核心內(nèi)容(下)
這篇文章主要給大家介紹了如何通過30分鐘快速入門掌握ES6/ES2015的核心內(nèi)容的相關(guān)資料,之前給大家介紹過基礎(chǔ)的一些內(nèi)容,下面繼續(xù)來介紹一些其他的新特性,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04
JavaScript數(shù)據(jù)可視化:ECharts制作地圖
這篇文章主要介紹了Echarts實(shí)現(xiàn)可視化地圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08
javascript AutoScroller 函數(shù)類
javascript AutoScroller 自動滾動類代碼,學(xué)習(xí)類的朋友可以參考下。2009-05-05
JavaScript內(nèi)存管理與閉包實(shí)例詳解
不管什么樣的編程語言,在代碼的執(zhí)行過程中都是需要給它分配內(nèi)存的,下面這篇文章主要給大家介紹了關(guān)于JavaScript內(nèi)存管理與閉包的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
Jvascript學(xué)習(xí)實(shí)踐案例(開發(fā)常用)
一些在Jvascript學(xué)習(xí)實(shí)踐的實(shí)例代碼,需要的朋友可以參考下2012-06-06
JS實(shí)現(xiàn)將Asp.Net的DateTime Json類型轉(zhuǎn)換為標(biāo)準(zhǔn)時間的方法
這篇文章主要介紹了JS實(shí)現(xiàn)將Asp.Net的DateTime Json類型轉(zhuǎn)換為標(biāo)準(zhǔn)時間的方法,涉及javascript針對時間與日期操作的相關(guān)技巧,需要的朋友可以參考下2016-08-08

