我知道设置Javascript属性属性的正确方法是使用Object.defineProperty函数,但我很好奇是什么阻止了直接在通过Object.getOwnPropertyDescriptor返回的描述符对象上设置这些值。
var a = new Object()
a.x = 1
var attributes = Object.getOwnPropertyDescriptor(a, 'x') //Object {value: 1, writable: true, enumerable: true, configurable: true}
var attributesOfWritable = Object.getOwnPropertyDescriptor(attributes, 'writable') //Object {value: true, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(a, 'x').writable = false
console.log(Object.getOwnPropertyDescriptor(a, 'x')) //Object {value: 1, writable: true, enumerable: true, configurable: true}
Object.defineProperty(a, 'x', {writable: false})
console.log(Object.getOwnPropertyDescriptor(a, 'x')) //Object {value: 1, writable: false, enumerable: true, configurable: true}
如上面的代码所示,当查看为ax的原始描述符对象上的'writable'属性返回的描述符对象时,该属性是可写和可配置的,这意味着设置writable
属性属性描述符未更改基础x
属性。
所以我不确定为什么我不能写:
Object.getOwnPropertyDescriptor(a, 'x').writable = false
答案 0 :(得分:4)
这是因为每次使用Object.getOwnPropertyDescriptor
时,FromPropertyDescriptor都会构建一个新的不同对象。
该对象没有特殊的setter,因此更改其数据不会影响原始对象的属性。
相反,您应该重新定义属性:
var getLiveDescriptor = (function() {
var map = new WeakMap(),
getDesc = Object.getOwnPropertyDescriptor;
return function getLiveDescriptor(obj, prop) {
var descriptors = map.get(obj);
if(!descriptors) map.set(obj, descriptors=Object.create(null));
var descriptor = descriptors[prop];
if(descriptor) return descriptor;
return descriptors[prop] = new Proxy({}, {
has(target, key) {
return key in getDesc(obj, prop);
},
get(target, key, receiver) {
return getDesc(obj, prop)[key];
},
set(target, key, value, receiver) {
var desc = getDesc(obj, prop);
desc[key] = value;
Object.defineProperty(obj, prop, desc);
return true;
},
ownKeys(target) {
return Object.getOwnPropertyNames(getDesc(obj, prop));
}
});
};
})();
Object.getOwnPropertyDescriptor(a, 'x').writable; // true
getLiveDescriptor(a, 'x').writable = false;
Object.getOwnPropertyDescriptor(a, 'x').writable; // false
否则,您可以构建自己的API,类似这样的
{{1}}