對象著手
在談原型鏈之前如捅,先了解對象,萬物皆對象调煎。
所有引用類型(函數(shù)镜遣,數(shù)組,對象)都擁有proto屬性(隱式原型)
所有函數(shù)擁有prototype屬性(顯式原型)(僅限函數(shù))
原型對象:擁有prototype屬性的對象士袄,在定義函數(shù)時就被創(chuàng)建
prototype與proto兩個概念
- prototype:此屬性只有構造函數(shù)才有悲关,它指向的是當前構造函數(shù)的原型對象。
- proto:此屬性是任何對象在創(chuàng)建時都會有的一個屬性娄柳,它指向了產生當前對象的構造函數(shù)的原型對象寓辱,由于并非標準規(guī)定屬性,不要隨便去更改這個屬性的值赤拒,以免破壞原型鏈秫筏,但是可以借助這個屬性來學習诱鞠,所謂的原型鏈就是由proto連接而成的鏈。
原型鏈詳解
在js代碼中
通過對象創(chuàng)建(下面一段簡單的代碼)詳細分析原型鏈
一段簡單代碼:
function foo(){}
foo.prototype.z=3;
var obj=new foo();
obj.y=2;
obj.x=1;
//調用
obj.x;//1
obj.y;//2
obj.z;//3
typeof obj.toString;//'function'
'z' in obj;//true
obj.hasOwnProperty('z');//false
obj.z=5;
obj.z;//5
'z' in obj;//true
obj.hasOwnProperty('z');//true
foo.prototype.z;//3
-
代碼簡單分析
上面一段代碼跳昼,聲明第一個函數(shù)foo的時候般甲,它就會帶一個foo.prototype的屬性肋乍,這個屬性是一個對象屬性鹅颊,用new foo();構造器的方式構造一個新的對象obj。這時候這個obj的原型會指向foo的prototype屬性墓造。 對于這個foo函數(shù)的原型也會指向Object.prototype,這個Object.prototype也是有原型的堪伍,它的原型指向null。
- 代碼對象原型鏈圖:
[圖片上傳失敗...(image-9f8e1d-1559386395923)]
-
對象訪問屬性順序
對象訪問屬性的順序觅闽,是采用向上查找帝雇,如果當前對象沒有,它會一直向上原型鏈中查找蛉拙,一直找到null尸闸,如果還沒有會返回undefind。
-
對象中值修改說明
代碼中修改obj.z的值后孕锄,再次輸出obj.z的時候是5,foo.prototype.z是3吮廉,說明我們在修改或添加對象的屬性的時候,只是修改了對象本身obj.prototype.z中的值畸肆,而原型鏈中foo.prototype.z的值并不會修改宦芦。
-
in,hasOwnProperty等方法的出現(xiàn)
首先查看整個原型鏈轴脐,會想這兩個方法是怎么來的调卑,在foo的的proto指向上一級Object.prototype的時候,就可以訪問Object中的一些函數(shù)和屬性了大咱,其中就包括這兩個方法恬涧。
第一次調用
'z' in obj;//true obj.hasOwnProperty('z');//false
表示的是z并不是obj這個對象上的,而是對象的原型鏈上的碴巾。
'z' in obj;//true obj.hasOwnProperty('z');//true foo.prototype.z;//3
第二次修改了obj.z的值气破,z就是obj這個對象上的了,但是也并沒有修改原型鏈中的z的值餐抢。
特殊說明
proto是每一個對象都有的屬性现使,它的指向會有一個特殊說明,大多數(shù)情況下 proto指向了產生當前對象的構造函數(shù)的原型對象旷痕,也就是那個 prototype碳锈。但是會有特殊的情況
- 特殊情況
var a={};
var b=Object.create(a);
object.create是創(chuàng)建了一個空對象,空對象的原型指向a欺抗,a也是空對象售碳,這其中不存在prototype;Object.create在繼承中也常被使用,創(chuàng)建一個空對象指向()內的對象,這這樣實現(xiàn)了b繼承a贸人,也不會篡改a中的內容间景,在這里就不具體說明了。
原理圖分析
總結
-
到底什么是原型鏈?
proto是任何對象都有的屬性艺智,在js中萬物皆對象倘要,所以會形成一條proto連起來的鏈條,遞歸訪問proto必須最終到頭十拣,并且值是null封拧。
<center>覺得本文對你有幫助?請分享給更多人<center>
歡迎大家關注我的公眾號——程序員成長指北夭问。請自行微信搜索——“程序員成長指北”