6

我正在做这样的事情:

var myObj = {a:1, b:2, c:3, d:4};

for (var key in myObj){
  if (someCondition){
    delete(myObj[key]);
  }
}

它在我尝试过的示例中工作得很好,但我不确定它在某些场景/浏览器中是否会出现意外行为。

修改被迭代的对象可以吗?

4

2 回答 2

8

第 12.6.4 节解释了它for..in是根据“下一个属性”定义的:

令 P 为 obj 的 [[Enumerable]] 属性为 true 的下一个属性的名称。如果没有这样的属性,返回(正常,V,空)。

由于即使存在突变(尽管迭代顺序不是),“下一个属性”的概念也得到了很好的定义,因此delete在迭代期间不会引入未定义的行为。

有一个极端情况,其中delete取消掩码原型属性,如

var obj = Object.create({ x: 1 });
obj.y = 2;
obj.x = 3;
for (var k in obj) {
  if (k == 'y') { delete obj.x; }
  alert(k);
}

在这种情况下,您可能会迭代y和删除x,您仍然应该x从原型中看到 ,但如果您x首先迭代,那么y您不应该看到第二个x

于 2012-07-09T19:13:19.580 回答
6

是的,它是安全的。

http://es5.github.com/#x12.6.4

12.6.4 for-in 语句

未指定枚举属性的机制和顺序(第一个算法中的步骤 6.a,第二个算法中的步骤 7.a)。被枚举对象的属性可能在枚举过程中被删除。如果在枚举期间还没有访问过的属性被删除,那么它就不会被访问。如果在枚举过程中向正在枚举的对象添加了新属性,则不能保证在活动枚举中访问新添加的属性。在任何枚举中不能多次访问属性名称。

于 2012-07-09T19:12:27.490 回答