【问题标题】:Is it safe to delete an object property while iterating over them?在迭代对象属性时删除它们是否安全?
【发布时间】:2011-03-28 15:25:53
【问题描述】:

当迭代对象的属性时,在 for-in 循环中删除它们是否安全?

例如:

for (var key in obj) {
    if (!obj.hasOwnProperty(key)) continue;

    if (shouldDelete(obj[key])) {
        delete obj[key];
    }
}

在许多其他语言中,遍历数组或字典并在其中删除是不安全的。 JS里可以吗?

(我正在使用 Mozilla 的 Spidermonkey 运行时。)

【问题讨论】:

  • 我已经开始对这个问题进行赏金,因为我认为当前的答案是不充分的,并且没有回答所提出的问题。如果适用,还请包括相关来源(希望来自规范)和任何值得注意的浏览器“怪癖”。

标签: javascript loops object properties


【解决方案1】:

ECMAScript 5.1 standard 第 12.6.4 节(关于 for-in 循环)说:

被枚举对象的属性可能在枚举过程中被删除。如果一个属性 枚举过程中还没有访问过的被删除,那么就不会被访问了。如果新的属性是 在枚举过程中添加到被枚举的对象中,新添加的属性不保证 在活动枚举中被访问。在任何枚举中不能多次访问属性名称。

所以我认为很明显 OP 的代码是合法的并且会按预期工作。浏览器怪癖通常会影响迭代顺序和删除语句,但不会影响 OP 代码是否有效。通常最好只删除迭代中的当前属性 - 删除对象中的其他属性将不可预测地导致它们被包含(如果已经访问)或不包含在迭代中,尽管这可能会或可能不会是一个问题,具体取决于情况。

另见:

但这些都不会真正影响 OP 的代码。

【讨论】:

  • 我刚刚注意到我包含了与另一个答案相同的标准引用,道歉。
【解决方案2】:

来自Javascript/ECMAScript specification(特别是12.6.4 The for-in Statement):

被枚举的对象的属性可能会被删除 枚举。如果在此期间尚未访问的属性 枚举被删除,则不会被访问。如果新属性 在枚举过程中被添加到被枚举的对象中,newly 不保证在活动中访问添加的属性 枚举。一个属性名称在任何时候都不能被访问超过一次 枚举。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多