在遍历对象属性时删除对象属性是否安全?


100

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

例如:

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

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

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

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


我开始悬赏这个问题,因为我认为当前答案不足,并且无法回答提出的问题。还请提供相关来源(希望来自规范)和任何著名的浏览器“怪癖”(如果适用)。
user2864740 2013年

Answers:


116

ECMAScript的5.1标准节12.6.4(上,中环路)说:

被枚举的对象的属性可以在枚举期间删除。如果在枚举过程中尚未访问的属性被删除,则将不会访问该属性。如果在枚举期间将新属性添加到要枚举的对象,则不能保证新添加的属性在活动枚举中被访问。在任何枚举中,不得多次访问属性名称。

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

也可以看看:

尽管这些都没有真正影响OP的代码。


1
我只是注意到我与其他答案一样道歉。
TomW

17

根据Javascript / ECMAScript规范(特别是12.6.4 for-in语句):

被枚举的对象的属性可以在枚举期间删除。如果在枚举过程中尚未访问的属性被删除,则将不会访问该属性。如果在枚举期间将新属性添加到要枚举的对象,则不能保证新添加的属性在活动枚举中被访问。在任何枚举中,不得多次访问属性名称。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.