web-dev-qa-db-ja.com

繰り返し処理中にオブジェクトプロパティを削除しても安全ですか?

オブジェクトのプロパティを反復処理するとき、for-inループ内でそれらを削除しても安全ですか?

例えば:

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

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

他の多くの言語では、配列または辞書を繰り返し処理し、その内部を削除することは安全ではありません。 JSでは大丈夫ですか?

(私はMozillaのSpidermonkeyランタイムを使用しています。)

94
Joe Shaw

ECMAScript 5.1標準 セクション12.6.4(for-inループ上)は次のように述べています。

列挙されているオブジェクトのプロパティは、列挙中に削除される場合があります。列挙中にまだ訪問されていないプロパティが削除された場合、そのプロパティは訪問されません。列挙中に列挙されているオブジェクトに新しいプロパティが追加された場合、新しく追加されたプロパティがアクティブな列挙でアクセスされるとは限りません。列挙内でプロパティ名に2回以上アクセスすることはできません。

したがって、OPのコードが合法であり、期待どおりに機能することは明らかです。ブラウザの癖は、一般に反復順序と削除ステートメントに影響しますが、OPsコードが機能するかどうかには影響しません。一般的には、反復で現在のプロパティを削除することのみが最善です。オブジェクト内の他のプロパティを削除すると、予期せずそれらが含まれ(すでにアクセスされている場合)、反復に含まれなくなりますが、状況。

以下も参照してください。

ただし、これらはどれも実際にはOPのコードに影響を与えません。

108
TomW

Javascript/ECMAScript仕様 (特に 12.6.4 for-inステートメント )から:

列挙されているオブジェクトのプロパティは、列挙中に削除される可能性があります。列挙中にまだ訪問されていないプロパティが削除された場合、そのプロパティは訪問されません。列挙中に列挙されているオブジェクトに新しいプロパティが追加された場合、新しく追加されたプロパティがアクティブな列挙でアクセスされることが保証されません。列挙内では、プロパティ名に2回以上アクセスすることはできません。

17
Chill