深入理解JavaScript之_pro_與prototype的區別

  首先拋出結論

  _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的原型對象。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章