Object.defineProperty与普通属性的区别

7

考虑到基本的使用情况,执行以下操作:

foo.bar = 'baz';

并且

Object.defineProperty(foo, 'bar', {
  value: 'baz',
  configurable: true,
  enumerable: true,
  writable: true
});

在支持的浏览器中是否能够完全一致地运行?

在ES6之前的应用程序中,我们是否可以因为语法更好而回退到普通的语法,或者混合使用二者而不产生任何副作用?


1
你的问题末尾有一个问号,但它并不是一个真正的问题。你能重新表达一下这个问题吗? - Richard Rout
当您定义一个属性时,如果没有使用defineProperty,则obj.property = 'value'和使用所有描述符对象的true值的defineProperty是相同的。但是,当您更改描述符对象的属性,例如configurable、enumerable或writable时,两种声明就会有所不同。 - Jagadish Dharanikota
在绝大多数情况下,它们的行为方式完全相同。然而,如果原型具有不同的属性描述符,则存在一种边缘情况:从已冻结的父对象创建新对象 - Qantas 94 Heavy
谢谢大家,先生们,这基本上就是我想知道的。 - Estus Flask
1个回答

4

是的,当

  • foo中没有bar属性(甚至没有继承的属性),因此将创建一个新属性;或者
  • bar属性已经存在,且其writableconfigurable属性都设置为true

然而,如果两种情况都不满足,它们确实会产生稍微不同的结果。

  • defineProperty 不考虑继承属性及其描述符
  • 如果现有(可能是继承的)属性是访问器属性,则赋值将尝试调用setter(如果不存在则失败),而 definePropery 将使用数据描述符覆盖该属性(如果它是自身的、不可配置的属性,则会失败)
  • 如果现有的继承属性是数据属性,则如果 writable 为false,则赋值将失败,如果为true,则会创建一个新的自身属性,就像defineProperty总是做的一样
  • 如果现有的自身属性是数据属性,则如果 writable 为false,则赋值将失败,如果为true,则将设置新值,而defineOwnProperty将在 configurable 为false时失败,否则将覆盖属性。

考虑基本使用的情况

如果“基本使用”是指不使用复杂的属性特性,则它们是等效的。但是,你应该只使用简单的赋值,因为它们更容易阅读和执行速度更快。

在 ES6 之前的应用中可以回退到原有方法吗?

请注意,完整支持 defineProperty 需要 ES5,因此,除非你需要考虑 ES5 之前的浏览器(如旧版 IE),否则你不需要关心这个问题。


另一个使行为相同的要求是假设Object是全局对象(未被遮蔽),并且全局Object及其defineProperty属性都没有被修改。 - Oriol
@Oriol:是啊,当然,我想Object.defineProperty是内置方法。 - Bergi
谢谢,Bergi,非常全面。 - Estus Flask

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接