This has been an age old question and I am aware of the usual reasons for not using for..in
or perhaps even objects when any sort of ordering is needed, but I recently came across this article from MDC on the delete operator.
Cross-browser issues
Although ECMAScript makes iteration order of objects implementation-dependent, it may appear that all major browsers support an iteration order based on the earliest added property coming first (at least for properties not on the prototype). However, in the case of Internet Explorer, when one uses delete on a property, some confusing behavior results, preventing other browsers from using simple objects like object literals as ordered associative arrays. In Explorer, while the property value is indeed set to undefined, if one later adds back a property with the same name, the property will be iterated in its old position--not at the end of the iteration sequence as one might expect after having deleted the property and then added it back.
So if you want to simulate an ordered associative array in a cross-browser environment, you are forced to either use two separate arrays (one for the keys and the other for the values), or build an array of single-property objects, etc.
It appears that most major browsers - Chrome, Safari, Firefox, and Opera enumerate object properties in insertion order. This is a quick test to confirm that. It may not work on IE, but I don't have access to IE to test this out unfortunately. So does IE preserve ordering as well (6/7 onwards) when iterating through properties using for..in
assuming we don't delete anything from the object?
Also, for..in
is never recommended for iterating through arrays for the exact same reasons, and the fact that Array.prototype
is more commonly tampered with than Object.prototype
. However, if properties were actually enumerated in insertion order, then I suppose for..in
can be used to loop over arrays as well, with the following gotcha - Properties listed on Array.prototype
will be enumerated as well.
There are two solutions to this:
Check if property belongs to the object using hasOwnProperty
for(var index in object) {
if(object.hasOwnProperty(index)) {
..
}
}
Use the new ES5 syntax for defining properties on objects and make them non-enumerable. This assumes that you have full control over the extension to base prototypes, and no 3rd party code adds anything on the prototype directly.
Object.defineProperty(Array.prototype, "size", {
enumerable: false,
configurable: false,
get: function() { return this.length; },
set: undefined
});
If all the above conditions are met, and unless I am missing something crucial, for..in
can be safely used for array iteration as well:
var values = [1, 2, 3];
for(var i in values) {
values[i];
}
So I guess it's back to the original question. Disregarding what the spec says, does IE support object iteration in insertion order, for any versions? Are there any other browsers that don't support this as well.