3

我想使用 Proxy 创建动态的不可配置属性。我试过这个:

const proxy = new Proxy({}, {
  getOwnPropertyDescriptor() {
    return {
      configurable: false,
      enumerable: false,
    };
  },
});

console.log(Reflect.getOwnPropertyDescriptor(proxy, 'test'));

但我收到一个错误:

TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property 'test' which is either non-existant or configurable in the proxy target

MDN说:

如果属性不作为目标对象的自有属性存在或作为目标对象的可配置自有属性存在,则不能将其报告为不可配置。

但它并没有解释这背后的原因是什么。

这个错误有什么解决方法吗?

4

2 回答 2

9

并不真地。这是由于理想的不变量,如果您观察到对象中的不可配置属性,它不会神奇地消失。如果它也是不可写的,它的值也不能改变。

如果不能依靠这个,getOwnPropertyDescriptor基本上就没有用了。

强制你不要使用不可配置的属性,或者在目标中定义它们,意味着你不会违反这个不变量,因为不变量通过构造在目标上成立。也就是说,ECMAScript 不允许您以破坏这些不变量的方式使用代理自定义。

6.1.7.3中定义的一些内部方法不变量是基本的完整性不变量。这些不变量由本节中指定的代理对象内部方法显式强制执行。ECMAScript 实现必须在存在所有可能的不变违规的情况下保持健壮。

因此,要么将属性报告为可配置,要么在目标中定义不可配置的属性。

如果你想要动态属性,我建议只是说属性是可配置的。然后添加一个defineProperty返回的陷阱false,有效地防止重新定义。

于 2016-12-01T23:09:20.133 回答
2

似乎如果在getOwnPropertyDescriptor陷阱内部我在返回描述符之前在目标对象上定义了该属性,它就可以正常工作。

const proxy = new Proxy({}, {
  getOwnPropertyDescriptor(target, property) {
    const descriptor = {
      configurable: false,
      enumerable: false,
    };
    Reflect.defineProperty(target, property, descriptor);
    return descriptor;
  },
});

console.log(Reflect.getOwnPropertyDescriptor(proxy, 'test'));

副作用(显然)是创建的属性,它不能被删除(因为它是不可配置的),这意味着例如我以后不能将它报告为不存在,但在我的情况下它并不重要。

于 2016-12-01T23:31:46.177 回答