Est-il sûr de supprimer une propriété d'objet lors de l'itération sur eux?

101

Lors d'une itération sur les propriétés d'un objet, est-il sûr de les supprimer dans une boucle for-in?

Par exemple:

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

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

Dans de nombreuses autres langues, itérer sur un tableau ou un dictionnaire et en supprimer à l'intérieur n'est pas sûr. Est-ce que ça va dans JS?

(J'utilise le runtime Spidermonkey de Mozilla.)

Joe Shaw
la source
J'ai commencé une prime sur cette question parce que je pense que la réponse actuelle est inadéquate et ne répond pas à la question telle que présentée . Veuillez également inclure une source pertinente (avec un peu de chance de la spécification) et toute «bizarrerie» notable du navigateur, le cas échéant.
user2864740

Réponses:

117

La section 12.6.4 de la norme ECMAScript 5.1 (sur les boucles for-in) dit:

Les propriétés de l'objet énuméré peuvent être supprimées pendant l'énumération. Si une propriété qui n'a pas encore été visitée lors de l'énumération est supprimée, elle ne sera pas visitée. Si de nouvelles propriétés sont ajoutées à l'objet énuméré pendant l'énumération, les propriétés nouvellement ajoutées ne sont pas garanties d'être visitées dans l'énumération active. Un nom de propriété ne doit pas être visité plus d'une fois dans une énumération.

Je pense donc qu'il est clair que le code du PO est légal et fonctionnera comme prévu. Les bizarreries du navigateur affectent l'ordre d'itération et suppriment les instructions en général, mais pas si le code OP fonctionnera. Il est généralement préférable de supprimer uniquement la propriété actuelle dans l'itération - la suppression d'autres propriétés de l'objet entraînera de manière imprévisible leur inclusion (si déjà visitée) ou non incluse dans l'itération, bien que cela puisse ou non être un problème selon le situation.

Voir également:

Cependant, aucun de ces éléments n'affecte vraiment le code de l'OP.

TomW
la source
1
Je viens de remarquer que j'ai inclus la même citation de normes que l'autre réponse, des excuses.
TomW
17

À partir de la spécification Javascript / ECMAScript (spécifiquement 12.6.4 l'instruction for-in ):

Les propriétés de l'objet énuméré peuvent être supprimées pendant l'énumération . Si une propriété qui n'a pas encore été visitée lors de l'énumération est supprimée, elle ne sera pas visitée. Si de nouvelles propriétés sont ajoutées à l'objet énuméré pendant l'énumération, les propriétés nouvellement ajoutées ne sont pas garanties d'être visitées dans l'énumération active . Un nom de propriété ne doit pas être visité plus d'une fois dans une énumération.

Refroidissement
la source