Javascript中的prototype和__proto__的聯系區別


一、聯系

prototype和__proto__都指向原型對象,任意一個函數(包括構造函數)都有一個prototype屬性,指向該函數的原型對象,同樣任意一個構造函數實例化的對象都有一個__proto__屬性(__proto__並非標准屬性,ECMA-262第5版將該屬性或指針稱為[[Prototype]],可通過Object.getPrototypeOf()標准方法訪問該屬性),指向構造函數的原型對象。如下代碼所示:

function a() {
    //console.log("I'am a function.");
}
//b是實例化對象,a是構造函數
var b = new a();

console.log(b.__proto__ == a.prototype);  //true
console.log(Object.getPrototypeOf(b) == a.prototype); //true,標准方法返回的結果和上述一樣

二、區別

基於上述的示例代碼,我們繼續稍微深入去看看prototype和__proto__的區別到底在哪里,如下:

//注意:a作為構造函數時的prototype屬性與a作為普通函數時的__proto__屬性並不相等
console.log(a.prototype == a.__proto__);//false

//這個怎么理解呢,我們再看看如下代碼
console.log(a.__proto__);         //function (){}
console.log(a.__proto__ == Function.prototype);//true

//實際上,a作為一個普通函數調用的時候,它的構造函數就是內置對象Function了,所以它指向的原型對象,自然對應就是Function.prototype.
//其實這個和console.log(b.__proto__ == a.prototype)是一樣的道理

//我們繼續看如下代碼,當a作為構造函數時,它的原型,和它的原型的原型都指向神馬
console.log(a.prototype);                   //a{}
console.log(a.prototype.__proto__);  //Object{}

//我們再看看a作為普通函數時,它原型的原型指向神馬
console.log(a.__proto__.__proto__); //Object{}

//即有以下結果
console.log(a.__proto__.__proto__ == a.prototype.__proto__); //true

//結論:prototype屬性可以給函數和對象添加可共享(繼承)的方法、屬性,而__proto__是查找某函數或對象的原型鏈方式
//因此,
有人說原型鏈實際是通過__proto__屬性鏈接起來的,也是有一定道理的

綜上所述,要理解prototype和__proto__的聯系區別,我認為主要需明確以下兩點,對理解prototype和__proto__是比較有用的:

  1. JavaScript中的函數是對象,而且除了使用字面量定義外,都需要通過函數來創建對象;
  2. prototype是構造函數訪問原型對象,__proto__是對象實例訪問原型對象。

三、參考資料

  1. 一個關於JavaScript作用域的問題,prototype和_proto_的區別
  2. 《JavaScript高級程序設計(第3版)》[美]Nicholas C.Zakas著 李松峰 曹力 譯,人民郵電出版社,第147頁-149頁
  3. http://www.ecma-international.org/ecma-262/6.0/index.html#sec-terms-and-definitions-prototype


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM