程序员

javascript原型——属性设置和屏蔽

2019-05-09  本文已影响8人  Y_d4ea

[[Prototype]]

JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,其实就是对于其他对象的引
用。几乎所有的对象在创建时 [[Prototype]] 属性都会被赋予一个非空的值。

[[Prototype]]作用:

1.试图引用对象的属性时会触发[[Get]] 操作
2.如果无法在对象本身找到需要的属性,就会继续访问对象
的 [[Prototype]] 链

var anotherObject = { a:2
};
// 创建一个关联到 anotherObject 的对象
var myObject = Object.create( anotherObject ); myObject.a; // 2
// Object.create()可理解成继承一个对象,添加的属性是在原型链下
// 添加的值不是自身的,通过原型链proto来访问

3.如果 anotherObject 中也找不到 a 并且 [[Prototype]] 链不为空的话,就会继续查找 下去。这个过程会持续到找到匹配的属性名或者查找完整条 [[Prototype]] 链。
4.所有普通的 [[Prototype]] 链最终都会指向内置的 Object.prototype。由于所有的“普通” (内置,不是特定主机的扩展)对象都“源于”(或者说把 [[Prototype]] 链的顶端设置为)这个Object.prototype 对象,所以它包含 JavaScript 中许多通用的功能。

属性设置和屏蔽
myObject.foo = "bar";
  1. 如果在[[Prototype]]链上层存在名为foo的普通数据访问属性并且没有被标记为只读(writable:false),那就会直接在myObject 中添加一个名为foo 的新 属性,它是屏蔽属性。
  2. 如果在[[Prototype]]链上层存在foo,但是它被标记为只读(writable:false),那么 无法修改已有属性或者在myObject 上创建屏蔽属性。如果运行在严格模式下,代码会抛出一个错误。否则,这条赋值语句会被忽略。总之,不会发生屏蔽。
  3. 如果在[[Prototype]]链上层存在foo并且它是一个setter,那就一定会 调用这个setter。foo不会被添加到(或者说屏蔽于)myObject,也不会重新定义 foo 这 个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,
实际上就是myObject.a=3。
2.用 [[Put]] 将值 3 赋给 myObject 中新建的屏蔽属性 a。
(如图,第一个对象为myObject,第二个对象为myObject)


WX20190509-103713@2x.png

注意:修改委托属性时一定要小心。如果想让 anotherObject.a 的值增加,唯一的办法是 anotherObject.a++。

上一篇下一篇

猜你喜欢

热点阅读