¿Es seguro eliminar una propiedad de un objeto mientras se itera sobre ellos?

100

Al iterar sobre las propiedades de un objeto, ¿es seguro eliminarlas en un bucle for-in?

Por ejemplo:

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

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

En muchos otros lenguajes, iterar sobre una matriz o diccionario y eliminarlo dentro no es seguro. ¿Está bien en JS?

(Estoy usando el tiempo de ejecución Spidermonkey de Mozilla).

Joe Shaw
fuente
He comenzado una recompensa por esta pregunta porque creo que la respuesta actual es inadecuada y no responde a la pregunta tal como se presenta . Incluya también una fuente relevante (con suerte de la especificación) y cualquier "peculiaridad" notable del navegador, si corresponde.
user2864740

Respuestas:

116

La sección 12.6.4 estándar de ECMAScript 5.1 (sobre bucles for-in) dice:

Las propiedades del objeto que se enumera pueden eliminarse durante la enumeración. Si se elimina una propiedad que aún no se ha visitado durante la enumeración, no se visitará. Si se agregan nuevas propiedades al objeto que se enumera durante la enumeración, no se garantiza que las propiedades recién agregadas se visiten en la enumeración activa. El nombre de una propiedad no debe visitarse más de una vez en cualquier enumeración.

Entonces, creo que está claro que el código del OP es legal y funcionará como se esperaba. Las peculiaridades del navegador afectan el orden de iteración y las declaraciones de eliminación en general, pero no si el código de OP funcionará. En general, es mejor eliminar solo la propiedad actual en la iteración: eliminar otras propiedades en el objeto hará que de manera impredecible se incluyan (si ya se visitaron) o no se incluirán en la iteración, aunque eso puede o no ser una preocupación según el situación.

Ver también:

Sin embargo, ninguno de estos afecta realmente el código del OP.

TomW
fuente
1
Me di cuenta de que incluí la misma cita estándar que la otra respuesta, disculpas.
TomW
17

De la especificación Javascript / ECMAScript (específicamente 12.6.4 La declaración for-in ):

Las propiedades del objeto que se enumera pueden eliminarse durante la enumeración . Si se elimina una propiedad que aún no se ha visitado durante la enumeración, no se visitará. Si se agregan nuevas propiedades al objeto que se enumera durante la enumeración, no se garantiza que las propiedades recién agregadas se visiten en la enumeración activa . El nombre de una propiedad no debe visitarse más de una vez en cualquier enumeración.

Frío
fuente