【问题标题】:Setting Javascript property attributes directly instead of Object.defineProperty直接设置 Javascript 属性属性而不是 Object.defineProperty
【发布时间】:2016-09-12 09:15:37
【问题描述】:

我知道设置 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

【问题讨论】:

    标签: javascript


    【解决方案1】:

    这是因为每次使用Object.getOwnPropertyDescriptorFromPropertyDescriptor 都会构建一个新的不同对象。

    该对象没有特殊的设置器,因此更改其数据不会影响原始对象的属性。

    相反,您应该重新定义属性:

    var desc = Object.getOwnPropertyDescriptor(a, 'x');
    desc.writable = false;
    Object.defineProperty(a, 'x', desc);
    

    否则,您可以构建自己的 API,类似这样

    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
    

    【讨论】:

      猜你喜欢
      • 2013-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多