我们现在考虑这么一种情况,假设有一个对象obj,我们要对其进行动态增加一个属性a,但是对象obj的[[Prototype]]原型链上面有属性a,那么我们为对象obj动态添加属性a是否一定会发生屏蔽现象呢?(即动态添加完之后,对象自身的a属性覆盖了原型链上的属性a)
对于上面这个问题,相信大部分人都会回答会屏蔽掉。然而事实并非如此,涉及到这种情况时的屏蔽问题会变得更加复杂。下面详细分析一下JavaScript对此做出的响应会有哪些:
- 1.如果在[[Prototype]]原型链上的那个同名属性的属性描述符writable被设置为true的话,那么就会直接在obj上动态添加这个属性。此时,会发生屏蔽工作。
Object.defineProperty(Object.prototype, "a", {
"value": "protoValue",
"writable": true,
"enumerable": true,
"configurable": true
})
var obj = {"b": 2}
console.log(obj.a)//"protoValue"
obj.a = "selfValue"
console.log(obj.a)//"selfValue"
- 2.如果在[[Prototype]]原型链上的那个同名属性的属性描述符writable被设置为false的话,那么在obj上动态增加这个属性将没有效果,不会发生屏蔽工作。在严格模式下,这样做会报错。
//"use strict";加上这句后报错
Object.defineProperty(Object.prototype, "a", {
"value": "protoValue",
"writable": false,
"enumerable": true,
"configurable": true
})
var obj = {"b": 2}
console.log(obj.b)//protoValue
obj.a = "selfValue"
console.log(obj.a)//protoValue
1.隐式屏蔽
有些情况下会发生隐式屏蔽,这个时候真的让人猝不及防,一不留神就造成了个错误。看下面这个例子:
var source_object = {"a": 2}
var target_object = Object.create(source_object)
console.log(source_object.a)//2
console.log(target_object.a)//2
source_object.hasOwnProperty("a")//true
target_object.hasOwnProperty("a")//false
target_object.a++//隐式屏蔽
source_object.a//2
target_object.a++//3
target_object.hasOwnProperty("a")//true
分析:可以这样理解target_object.a = target_object.a + 1;由于[[Prototype]]原型链上的a属性的属性描述符writable的值时true,所以此时发生了屏蔽现象。