【问题标题】:Create dynamic non-configurable properties using Proxy使用代理创建动态不可配置属性
【发布时间】:2016-12-01 22:52:54
【问题描述】:

我想使用 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 说:

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

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

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

【问题讨论】:

    标签: javascript ecmascript-6 es6-proxy


    【解决方案1】:

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

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

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

    6.1.7.3 中定义的一些内部方法不变量是 基本完整性不变量。这些不变量是明确的 由 this 中指定的代理对象内部方法强制执行 部分。 ECMAScript 实现在存在时必须是健壮的 所有可能的不变违规。

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

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

    【讨论】:

    • 很好的解释,谢谢。您如何看待我的解决方案(作为自我回答发布)?有没有我没有想到的副作用?
    • @Gothdo 是的,应该可以正常工作。您可能会遇到更通用的目标(例如另一个代理或不可扩展对象)的问题,但如果您使用 {} 并且不将其暴露给其他代码,我看不出有任何问题。
    • 为什么会有这个限制?
    【解决方案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'));

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

    【讨论】:

      猜你喜欢
      • 2021-09-03
      • 2021-09-12
      • 2020-06-02
      • 2014-07-13
      • 1970-01-01
      • 1970-01-01
      • 2021-09-24
      • 2020-01-08
      相关资源
      最近更新 更多