[[Prototype]]
JavaScript 中的對(duì)象有一個(gè)特殊的 [[Prototype]] 內(nèi)置屬性,其實(shí)就是對(duì)于其他對(duì)象的引
用。幾乎所有的對(duì)象在創(chuàng)建時(shí) [[Prototype]] 屬性都會(huì)被賦予一個(gè)非空的值。
[[Prototype]]作用:
1.試圖引用對(duì)象的屬性時(shí)會(huì)觸發(fā)[[Get]] 操作
2.如果無法在對(duì)象本身找到需要的屬性,就會(huì)繼續(xù)訪問對(duì)象
的 [[Prototype]] 鏈
var anotherObject = { a:2
};
// 創(chuàng)建一個(gè)關(guān)聯(lián)到 anotherObject 的對(duì)象
var myObject = Object.create( anotherObject ); myObject.a; // 2
// Object.create()可理解成繼承一個(gè)對(duì)象,添加的屬性是在原型鏈下
// 添加的值不是自身的,通過原型鏈proto來訪問
3.如果 anotherObject 中也找不到 a 并且 [[Prototype]] 鏈不為空的話,就會(huì)繼續(xù)查找 下去。這個(gè)過程會(huì)持續(xù)到找到匹配的屬性名或者查找完整條 [[Prototype]] 鏈。
4.所有普通的 [[Prototype]] 鏈最終都會(huì)指向內(nèi)置的 Object.prototype。由于所有的“普通” (內(nèi)置,不是特定主機(jī)的擴(kuò)展)對(duì)象都“源于”(或者說把 [[Prototype]] 鏈的頂端設(shè)置為)這個(gè)Object.prototype 對(duì)象,所以它包含 JavaScript 中許多通用的功能。
屬性設(shè)置和屏蔽
myObject.foo = "bar";
- 如果在[[Prototype]]鏈上層存在名為foo的普通數(shù)據(jù)訪問屬性并且沒有被標(biāo)記為只讀(writable:false),那就會(huì)直接在myObject 中添加一個(gè)名為foo 的新 屬性,它是屏蔽屬性。
- 如果在[[Prototype]]鏈上層存在foo,但是它被標(biāo)記為只讀(writable:false),那么 無法修改已有屬性或者在myObject 上創(chuàng)建屏蔽屬性。如果運(yùn)行在嚴(yán)格模式下,代碼會(huì)拋出一個(gè)錯(cuò)誤。否則,這條賦值語句會(huì)被忽略??傊?,不會(huì)發(fā)生屏蔽。
- 如果在[[Prototype]]鏈上層存在foo并且它是一個(gè)setter,那就一定會(huì) 調(diào)用這個(gè)setter。foo不會(huì)被添加到(或者說屏蔽于)myObject,也不會(huì)重新定義 foo 這 個(gè)setter。
例如:
var anotherObject = {
a: 2
};
var myObject = Object.create(anotherObject);
anotherObject.a; // 2
myObject.a; // 2
anotherObject.hasOwnProperty("a"); // true
myObject.hasOwnProperty("a"); // false
myObject.a++; // 隱式屏蔽!
anotherObject.a; // 2
myObject.a; // 3
myObject.hasOwnProperty("a"); // true
通俗易懂來說:
1.myObject.a++分解為myObject.a=myObject.a+1,
實(shí)際上就是myObject.a=3。
2.用 [[Put]] 將值 3 賦給 myObject 中新建的屏蔽屬性 a。
(如圖,第一個(gè)對(duì)象為myObject,第二個(gè)對(duì)象為myObject)

注意:修改委托屬性時(shí)一定要小心。如果想讓 anotherObject.a 的值增加,唯一的辦法是 anotherObject.a++。