在迭代对象属性时删除它们是否安全?

2022-08-30 05:18:50

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

例如:

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

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

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

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


答案 1

ECMAScript 5.1 标准部分 12.6.4(关于 for-in 循环)说:

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

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

另请参阅:

不过,这些都不会影响OP的代码。


答案 2

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

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