for循环期间的Javascript关联数组修改

时间:2011-05-21 12:54:19

标签: javascript foreach associative-array

javascript for关键字将迭代对象的所有属性。如果在循环体内修改了对象,会发生什么?

例如,以下代码是否正常?

for(var key in obj)
    if (whatever(obj[key]))
        delete obj[key];

如果此代码以确定的方式工作,并且最好obj中的所有密钥都只测试一次,那就OK。相比之下,在.NET或Java中,类似的构造通常会抛出异常。

2 个答案:

答案 0 :(得分:8)

我认为它有效。请小心要求hasOwnProperty(key) - 因为for也会愉快地迭代继承的属性(和方法,它们只是带有函数值的属性)。

另外:http://www.w3schools.com/js/js_loop_for_in.asp说:

  

注意:for ... in循环体中的代码对每个属性执行一次。

另外:https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in说:

  

for ... in循环以任意顺序迭代对象的属性(有关为什么不能依赖于迭代的看似有序性的原因,请参阅delete运算符,至少在跨浏览器设置中)。如果在一次迭代中修改属性,然后在稍后访问该属性,则循环公开的值将是其稍后的值。在访问之前删除的属性将不会在以后访问。添加到正在进行迭代的对象的属性可以在迭代中被访问或省略。通常,除了当前正在访问的属性之外,最好不要在迭代期间添加,修改或删除对象的属性;无法保证是否会访问添加的属性,是否在修改之前或之后访问修改后的属性,或者删除属性是否会被删除。

我从中读到的是 - 如果你正在修改当前值之外的其他值,那么非确定性可能会让你陷入困境。但是,修改当前版本应该没问题。

答案 1 :(得分:0)

可以在使用 for-in 迭代对象的同时修改对象的属性。问题是:你应该关心吗?很容易重写代码,首先创建属性列表,然后删除符合删除条件的属性。

例如,如果您想删除某些不是函数且未被继承的属性:

var keys = Object.keys(obj).filter(k=>!(obj[k] instanceof Function))
for(var key of keys)
  if(whatever(obj[key]))
    delete obj[key];

一般来说,最好编写不会引起像您提出的问题那样棘手的问题的代码。

请注意,此代码假定您的运行时环境中存在 Object.keys()。较旧的浏览器可能不支持此功能,因此如果您需要支持这些浏览器,则可能需要找到解决方法。