I'm doing something like this:
var myObj = {a:1, b:2, c:3, d:4};
for (var key in myObj){
if (someCondition){
delete(myObj[key]);
}
}
It works just fine in the samples I've tried, but I'm not sure if it might have an unexpected behavior in certain scenarios/browsers.
Is it ok to modify the object being iterated?
I'm doing something like this:
var myObj = {a:1, b:2, c:3, d:4};
for (var key in myObj){
if (someCondition){
delete(myObj[key]);
}
}
It works just fine in the samples I've tried, but I'm not sure if it might have an unexpected behavior in certain scenarios/browsers.
Is it ok to modify the object being iterated?
Share Improve this question asked Jul 9, 2012 at 19:09 willvvwillvv 8,64916 gold badges68 silver badges103 bronze badges 5- 1 Past experience I've had suggests this could do bad things in IE7 and 8. I found most browsers take a "snapshot" of the keys before iterating, whereas IE7/8 seemed to use them "live" – Matt Greer Commented Jul 9, 2012 at 19:12
-
I'd take a look at this post. It has some good links on delete. He's iterating over an array, not object properties, but it might be helpful to understand how
delete
modifies the object. – DBueno Commented Jul 9, 2012 at 19:15 - @MattGreer: Is that with respect to deleting properties, or adding properites? – user1106925 Commented Jul 9, 2012 at 19:16
- @amnotiam For me it was adding properties. Deleting does seem safer in general (and the spec appears to support it), but if it was me I'd still give IE7/8 a good testing. – Matt Greer Commented Jul 9, 2012 at 19:20
- @MattGreer: Yes, always good advice. I do remember IE issues with adding properties. Seemed that they were always added to the unenumerated set, which probably isn't incorrect, but did differ from other implementations. Also made doing a property "replace" into an infinite loop. – user1106925 Commented Jul 9, 2012 at 19:22
2 Answers
Reset to default 8Section 12.6.4 explains that for..in
is defined in terms of the "next property":
Let P be the name of the next property of obj whose [[Enumerable]] attribute is true. If there is no such property, return (normal, V, empty).
Since the concept "next property" is well defined even in the presence of mutation (though iteration order is not), delete
during iteration does not introduce undefined behavior.
There is a corner case where delete
un-masks a prototype property as in
var obj = Object.create({ x: 1 });
obj.y = 2;
obj.x = 3;
for (var k in obj) {
if (k == 'y') { delete obj.x; }
alert(k);
}
In this case, where you might iterate y
and delete x
, you should still see the x
from the prototype, but if you iterated x
first, then y
you should not see the second x
.
Yes it is safe.
http://es5.github./#x12.6.4
12.6.4 The for-in Statement
The mechanics and order of enumerating the properties (step 6.a in the first algorithm, step 7.a in the second) is not specified. Properties of the object being enumerated may be deleted during enumeration. If a property that has not yet been visited during enumeration is deleted, then it will not be visited. If new properties are added to the object being enumerated during enumeration, the newly added properties are not guaranteed to be visited in the active enumeration. A property name must not be visited more than once in any enumeration.