1

当向一个对象添加多个属性时,添加它们Object.defineProperties()通常会产生比一个一个或一组添加更清晰、更易读的代码。

但是,如果一个属性引用另一个属性,Object.defineProperties()则无法处理它。考虑一个虚拟示例:

var foo = {};
Object.defineProperties(foo, {
    "one" : {value: 1, enumerable: true},
    "two" : {value: foo.one + 1, enumerable: true}
})
console.log(foo); // { one: 1, two: NaN }

var bar = {};
Object.defineProperties(bar,{
    "one" : {value: 1, enumerable: true}
}); 
Object.defineProperties(bar,{
    "two" : {value: bar.one + 1, enumerable: true}
});

console.log(bar); // { one: 1, two: 2 }

现在很明显,第二种解决方案总是有效的。但是,有人会假设第一个也可以工作,因为它似乎是另一个的简写,并且无论如何都建议对属性进行顺序处理。

我没有找到关于此的明确文档。

所以问题是:

  • 这是有意的限制,还是背景中的技术复杂性?
  • 它是否记录在某处?
  • 它是实现特定的还是标准的行为?

编辑:回答清楚,并在那里查看我的评论。这是一个简单的对象字面量问题(不是问题,而是 :),与 Object.defineProperties() 没有直接关系。

4

1 回答 1

4

这个问题其实和 没有太大关系Object.defineProperties()。问题在于对象初始值设定项表达式(“对象文字”是另一个术语)的评估方式。对象初始化器一个表达式,在它被评估之前,它正在初始化的对象并不真正存在。因此,在

Object.defineProperties(foo, {
    "one" : {value: 1, enumerable: true},
    "two" : {value: foo.one + 1, enumerable: true}
});

对象初始化子表达式是

{
    "one" : {value: 1, enumerable: true},
    "two" : {value: foo.one + 1, enumerable: true}
}

这必须在调用之前进行评估Object.defineProperties()。在它被评估的时候,foo没有一个叫做“一”的属性;即使确实如此,正在评估对象初始值设定项时的值也将是之前的值,而不是新值。

这正是对象初始化表达式的工作方式。无法直接从表达式中引用正在初始化的对象。这意味着即使在这样的声明中:

var foo = {
    "one" : {value: 1, enumerable: true},
    "two" : {value: foo.one + 1, enumerable: true}
};

你仍然有同样的问题。

于 2015-08-18T13:50:05.740 回答