首先拋出結論
_pro_是對象中特有的內置私有屬性,表示該對象的原型對象。此屬性不是JavaScript中的標準屬性但是卻有許多瀏覽器能夠實現。在ECMAScript標準中,正確的寫法應該是[[Prototype]],也就是說_pro_===[[Prototype]],這兩個屬性等價於Object.getPrototypeOf(...)方法,作用都是訪問對象的原型。
var a=3;
var foo={
a:2
};
var bar=Object.create(foo); //構建原型鏈:bar.prototype---->foo.prototype---->Object.prototype---->null
console.log(bar.__proto__.a); //2 bar._proto_指向bar的原型對象foo
console.log(foo.__proto__.a); //undefined foo._proto_指向foo的原型對象
我們利用對象中存在的_proto_屬性,訪問對象的原型對象,輸出a。但是,我們可以看到,原型鏈:bar.prototype--->foo.prototype--->Object.prototype--->null。foo的原型對象是Object,我們在全局詞法作用域中定義了一個"a",結果輸出的卻是:undefined??? 答案是:我們在全局作用域中定義的"a"實際上是一個對象,此對象是Object的實例,因此它的原型鏈是:a.prototype--->Object.prototype--->null
prototype則是函數特有的私有屬性,對象不一定有,函數幾乎都有,因爲函數是可調用的對象,因而函數中也存在_pro_屬性。此屬性類似一個指針,指向的是一個對象,此對象是"new"創建構造調用的對象的原型,通過此對象,函數與創建對象可共享對象中的方法和屬性。
function foo() {
}
foo.prototype={ //相當於foo的原型對象,因爲bar._pro_===foo.prototype,所以它們共享foo.prototype中的屬性和方法
a:2,
tostring:function (a) {
return this.a=a;
}
};
var bar=new foo(); //構造調用foo創建對象bar
console.log(bar.a); //2 bar中沒有此屬性,是通過原型鏈查找的
console.log(bar.tostring(3)); //3 bar沒有此方法 是通過原型鏈查找的
console.log(bar._pro_===foo.prototype) //true 可見對象的原型對象是函數的prototype指向對象
console.log(Object.getPrototypeOf(bar)===foo.prototype); //true
那麼foo.prototype是否是foo函數的原型呢?我們來實驗下,在以上代碼中加入
console.log(bar._pro_===Object.getPrototypeOf(foo)) //false
從上可以看出,並不是,也就是函數中的prototype屬性指向的是創建對象的原型對象而不是函數的原型對象。實際上定義的函數的原型基本上都是"Function"對象,此對象的原型是"Object"
MDZ中是這麼描述的:
遵循ECMAScript標準,
someObject.[[Prototype]]
符號是用於指向someObject
的原型。從 ECMAScript 6 開始,[[Prototype]]
可以通過Object.getPrototypeOf()
和Object.setPrototypeOf()
訪問器來訪問。這個等同於 JavaScript 的非標準但許多瀏覽器實現的屬性__proto__
。但它不應該與構造函數
func
的prototype
屬性相混淆。被構造函數創建的實例對象的[[prototype]]
指向func
的prototype
屬性。Object.prototype
屬性表示Object
的原型對象。