Apakah aman untuk menghapus properti objek saat mengulanginya?

100

Saat melakukan iterasi pada properti objek, apakah aman untuk menghapusnya saat berada dalam loop for-in?

Sebagai contoh:

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

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

Dalam banyak bahasa lain melakukan iterasi pada larik atau kamus dan menghapus bagian dalamnya tidak aman. Apakah tidak masalah di JS?

(Saya menggunakan runtime Spidermonkey Mozilla.)

Joe Shaw
sumber
Saya telah memulai pemberian hadiah atas pertanyaan ini karena menurut saya jawaban saat ini tidak memadai dan tidak menjawab pertanyaan seperti yang disajikan . Harap sertakan juga sumber yang relevan (mudah-mudahan dari spesifikasi) dan "kebiasaan" browser terkenal, jika berlaku.
pengguna2864740

Jawaban:

116

Bagian standar ECMAScript 5.1 12.6.4 (pada loop for-in) mengatakan:

Properti dari objek yang dicacah dapat dihapus selama pencacahan. Jika suatu properti yang belum dikunjungi saat pencacahan dihapus, maka properti tersebut tidak akan dikunjungi. Jika properti baru ditambahkan ke objek yang akan dihitung selama pencacahan, properti yang baru ditambahkan tidak dijamin akan dikunjungi dalam pencacahan aktif. Nama properti tidak boleh dikunjungi lebih dari sekali dalam pencacahan apapun.

Jadi saya pikir sudah jelas bahwa kode OP itu legal dan akan berfungsi seperti yang diharapkan. Kebiasaan browser memengaruhi urutan iterasi dan pernyataan hapus secara umum, tetapi tidak apakah kode OP akan berfungsi. Biasanya yang terbaik adalah menghapus properti saat ini dalam iterasi - menghapus properti lain dalam objek secara tidak terduga akan menyebabkannya disertakan (jika sudah dikunjungi) atau tidak disertakan dalam iterasi, meskipun itu mungkin atau mungkin tidak menjadi perhatian tergantung pada situasi.

Lihat juga:

Tak satu pun dari ini benar-benar mempengaruhi kode OP.

TomW
sumber
1
Saya baru menyadari bahwa saya memasukkan kutipan standar yang sama dengan jawaban lainnya, maaf.
TomW
17

Dari spesifikasi Javascript / ECMAScript (khususnya 12.6.4 Pernyataan for-in ):

Properti dari objek yang dicacah dapat dihapus selama pencacahan . Jika suatu properti yang belum dikunjungi saat pencacahan dihapus, maka properti tersebut tidak akan dikunjungi. Jika properti baru ditambahkan ke objek yang sedang dihitung selama pencacahan, properti yang baru ditambahkan tidak dijamin akan dikunjungi dalam pencacahan aktif . Nama properti tidak boleh dikunjungi lebih dari sekali dalam pencacahan apapun.

Dingin
sumber