Javascript:使用'for'删除正在迭代的对象的属性是否安全

时间:2012-07-09 19:09:52

标签: javascript

我正在做这样的事情:

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

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

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

可以修改正在迭代的对象吗?

2 个答案:

答案 0 :(得分:8)

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

  

设P是[[Enumerable]]属性为true的obj的下一个属性的名称。如果没有这样的属性,则返回(正常,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

答案 1 :(得分:6)

是的,这是安全的。

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

  

12.6.4 for-in Statement

     

未指定枚举属性的机制和顺序(第一个算法中的步骤6.a,第二个算法中的步骤7.a)。 枚举期间可能会删除要枚举的对象的属性。如果删除枚举期间尚未访问的属性,则不会访问该属性。如果在枚举期间将新属性添加到要枚举的对象,则不保证在新的属性中访问新属性。活跃的枚举。在任何枚举中不得多次访问属性名称。