【问题标题】:Why is it Object.defineProperty() rather than this.defineProperty() (for objects)?为什么是 Object.defineProperty() 而不是 this.defineProperty() (对于对象)?
【发布时间】:2012-10-25 17:08:45
【问题描述】:

我正在开发一个 JavaScript 项目,只是想知道为什么对象实例不继承 defineProperty() 和其他方法,而不必调用超类(超对象?)Object 方法。

我看过MDN docs,其实有“非标准”的属性方法。

但那些已被弃用。为什么要转向Object 方法?

在我看来,instance.defineProperty(...) 之类的东西比 Object.defineProperty(instance, ...) 更好。我也会对其他一些 Object 方法说同样的话。

【问题讨论】:

标签: javascript ecmascript-5


【解决方案1】:

有趣。到目前为止,我想出的唯一原因是人们喜欢重写原型,并且像这样“隐藏”这种方法可能会帮助您避免一些错误。尤其是因为方法名称很好,因为它比__defineGetter__ 更容易被重写。

似乎很多功能都依赖于此功能 (link),因此在这种情况下使其更加全球化和安全是有意义的。

【讨论】:

    【解决方案2】:

    这样做是为了避免冲突 - 请记住,Object.prototype 上的每个方法也是每个用户定义对象中的一个方法。

    想象一个对象,您需要一个自定义方法 defineProperty - 当 Object.defineProperty 位于其原型上时,这将完全破坏事物。

    【讨论】:

      【解决方案3】:

      这是为了避免冲突 - 通常,对象不具有您期望的值的属性。
      JS 中的对象通常用作键值映射,键可以是任意字符串——例如__defineGetter__hasOwnProperty 或其他不那么特别的东西。现在,当你想在未知对象上调用这样的函数时——比如 hasOwnProperty 经常用于泛型枚举函数中,其中任何 JSON 都可能被传入——你永远无法确定你是否有一个被覆盖的属性(甚至可能没有是一个函数)或您想要的原始文件,或者对象是否完全继承了该属性。为了避免这个问题(或者this IE bug),你必须使用Object.prototype.hasOwnProperty.call——这很难看。

      因此,在Object 上为所有这些函数命名空间只是有用的,它是一个更简洁的 API,将反射方法与对象的应用程序接口分开。这也有助于优化(简化静态分析)并更容易限制沙箱中反射 API 的访问 - 至少 design idea 是这样。

      您可能很高兴在原型中使用defineProperty,但您只能在使用已知对象时安全地使用它。如果你仍然想要它(你知道什么时候用什么时候不用),你可以使用

      Object.defineProperty(Object.prototype, "defineProperty", {
          writable: true,
          enumberable: false,
          value: function(prop, descr) {
              return Object.defineProperty(this, prop, descr); 
          }
      });
      

      【讨论】:

      • 同样值得注意的是,在 ES5 中对象不必继承自 Object.prototype。他们可以通过Object.create(null) 从无到有继承,或者他们可以从继承自null 的对象继承。这是非常有用的行为,但如果一个对象不是从Object.prototype 继承的,它就不会在Object.prototype 上定义方法。任何想要一般使用defineProperty 的库都必须使用var defineProperty = Function.prototype.call.bind(Object.prototype.defineProperty);,因此将其定义为实用函数而不是方法是有意义的。
      • 实际上,真正的原因是沙盒和更好的 API - 我可以证明这一点,但“rationale_for_es3_1_static_object_methodsaug26.pdf”已经死了。
      • @BenjaminGruenbaum “更好的 API”有点模棱两可——我认为它更好,因为它避免了冲突。沙盒是什么意思?
      • @BenjaminGruenbaum 我更新了答案,但不同意沙盒的原因。我认为这是使用 Meta 对象的一个​​论据 - 当您编写沙箱时,限制对 Object.defineProperty {}.constructor.defineProperty 的访问比仅限制对 {}.defineProperty 的访问更简单.
      猜你喜欢
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      • 2020-08-10
      • 2011-10-19
      • 2011-10-06
      • 2010-10-15
      • 2016-07-08
      相关资源
      最近更新 更多