我正在做这样的事情:
var myObj = {a:1, b:2, c:3, d:4};
for (var key in myObj){
if (someCondition){
delete(myObj[key]);
}
}
它在我尝试过的示例中运行得很好,但我不确定它在某些场景/浏览器中是否会出现意外行为。
可以修改正在迭代的对象吗?
答案 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)。 枚举期间可能会删除要枚举的对象的属性。如果删除枚举期间尚未访问的属性,则不会访问该属性。如果在枚举期间将新属性添加到要枚举的对象,则不保证在新的属性中访问新属性。活跃的枚举。在任何枚举中不得多次访问属性名称。