從上一篇文章JavaScript:prototype屬性,我們知道了在Javascript中,原型是用來(lái)設(shè)置一個(gè)構(gòu)造函數(shù)所生成的所有對(duì)象共有的屬性與函數(shù)的方法,它通過(guò)函數(shù)的prototype屬性開放給我們使用。那么問(wèn)題來(lái)了,給定一個(gè)對(duì)象o,如何知道它所對(duì)應(yīng)的原型是什么呢?這里我們要用到對(duì)象的內(nèi)部屬性[[Prototype]]。
我們先來(lái)看一個(gè)例子:
// 定義一個(gè)函數(shù)Car
function Car(brand, year) {
// 創(chuàng)建實(shí)例變量brand和year
this.brand = brand;
this.year = year;
}
// 創(chuàng)建實(shí)例方法getBrand
Car.prototype.getBrand = function() {
return this.brand;
};
// 創(chuàng)建實(shí)例方法getYear
Car.prototype.getYear = function() {
return this.year;
}
// 從函數(shù)Car創(chuàng)建一個(gè)對(duì)象
let my_car = new Car("瑪莎拉蒂", 2014);
console.log(Object.getPrototypeOf(my_car) === Car.prototype); // true
console.log(my_car.getBrand()); // 瑪莎拉蒂
console.log(my_car.getYear()); // 2014
當(dāng)我們用let car = new Car()新建一個(gè)對(duì)象時(shí),我們實(shí)際創(chuàng)建了如下圖所示的結(jié)構(gòu):

當(dāng)我們使用函數(shù)來(lái)創(chuàng)建一個(gè)對(duì)象時(shí),所使用的函數(shù)又被叫作這個(gè)對(duì)象的構(gòu)造函數(shù)。在對(duì)象被創(chuàng)建后,對(duì)象內(nèi)部會(huì)有一個(gè)內(nèi)部屬性[[Prototype]],指向它的構(gòu)造函數(shù)的prototype。在這里,兩對(duì)方括號(hào)"[[]]"代表這個(gè)屬性是內(nèi)部屬性。需要注意的是,內(nèi)部屬性[[Prototype]]無(wú)法直接在代碼中使用,要用函數(shù)Object.getPrototypeOf來(lái)獲取它的值,用函數(shù)Object.setPrototypeOf來(lái)改變它的值。
有了這種結(jié)構(gòu),當(dāng)我們調(diào)用my_car.getBrand()的時(shí)候,Javascript引擎就能夠通過(guò)內(nèi)部屬性[[Prototype]]找到相應(yīng)構(gòu)造函數(shù)的prototype,并進(jìn)一步找到函數(shù)getBrand。這樣一來(lái),所有通過(guò)構(gòu)造函數(shù)Car創(chuàng)建的對(duì)象,都具有了getBrand和getYear這兩個(gè)函數(shù)。
所有的對(duì)象都有內(nèi)部屬性[[Prototype]]。
大多數(shù)Javascript引擎都會(huì)實(shí)現(xiàn)一個(gè)叫做__proto__的屬性,從而讓開發(fā)者可以直接通過(guò)car.__proto__來(lái)直接讀取其內(nèi)部屬性[[Prototype]]。
遵循ECMAScript標(biāo)準(zhǔn),
someObject.[[Prototype]]符號(hào)是用于指向someObject的原型。從 ECMAScript 6 開始,[[Prototype]]可以通過(guò)Object.getPrototypeOf()和Object.setPrototypeOf()訪問(wèn)器來(lái)訪問(wèn)。這個(gè)等同于 JavaScript 的非標(biāo)準(zhǔn)但許多瀏覽器實(shí)現(xiàn)的屬性__proto__。
但需要注意的是,__proto__屬性并非ECMAScript標(biāo)準(zhǔn)推薦使用的屬性,它只在ECMAScript 2015 Language Specification的附錄中出現(xiàn),并且是作為棄用的特性,參考Object.prototype.__proto__ | MDN。
更多關(guān)于原型的探討請(qǐng)參見: