全部引用類型(函數,數組,對象)都擁有__proto__屬性(隱式原型)web
全部函數擁有prototype屬性(顯式原型)(僅限函數)面試
原型對象:擁有prototype屬性的對象,在定義函數時就被建立數組
在js代碼中 經過對象建立(下面一段簡單的代碼)詳細分析原型鏈 一段簡單代碼:函數
code
function foo(){} foo.prototype.z=3;var obj=new foo(); obj.y=2; obj.x=1;post
//調用 obj.x;//1 obj.y;//2學習
obj.z;//3spa
typeof obj.toString;//'function' 'z' in obj;//true obj.hasOwnProperty('z');//falseprototype
複製代碼obj.z=5; obj.z;//5 'z' in obj;//true obj.hasOwnProperty('z');//true foo.prototype.z;//3 複製代碼
上面一段代碼,聲明第一個函數foo的時候,它就會帶一個foo.prototype的屬性,這個屬性是一個對象屬性,用new foo();構造器的方式構造一個新的對象obj。這時候這個obj的原型會指向foo的prototype屬性。 對於這個foo函數的原型也會指向Object.prototype,這個Object.prototype也是有原型的,它的原型指向null。orm
對象訪問屬性的順序,是採用向上查找,若是當前對象沒有,它會一直向上原型鏈中查找,一直找到null,若是尚未會返回undefind。
代碼中修改obj.z的值後,再次輸出obj.z的時候是5,foo.prototype.z是3,說明咱們在修改或添加對象的屬性的時候,只是修改了對象自己obj.prototype.z中的值,而原型鏈中foo.prototype.z的值並不會修改。
首先查看整個原型鏈,會想這兩個方法是怎麼來的,在foo的的proto指向上一級Object.prototype的時候,就能夠訪問Object中的一些函數和屬性了,其中就包括這兩個方法。
第一次調用
'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_是每個對象都有的屬性,它的指向會有一個特殊說明,大多數狀況下 _proto_指向了產生當前對象的構造函數的原型對象,也就是那個 prototype。可是會有特殊的狀況
var a={};
var b=Object.create(a);
複製代碼
object.create是建立了一個空對象,空對象的原型指向a,a也是空對象,這其中不存在prototype;Object.create在繼承中也常被使用,建立一個空對象指向()內的對象,這這樣實現了b繼承a,也不會篡改a中的內容,在這裏就不具體說明了。
原理圖分析
proto是任何對象都有的屬性,在js中會造成一條proto連起來的鏈條,遞歸訪問proto必須最終到頭,而且值是null。
寫這篇總結的過程當中,發現不少文章都寫了「JS中萬物皆對象」。難道真的是這樣嗎? 錯,JS世界很大,並不僅有對象!推薦你們看這篇文章
再來看到底JS中萬物皆對象是否正確 ,是否是還有許多其餘類型。
以爲本文對你有幫助?請分享給更多人
複製代碼