Does the \"for…in\" loop in Javascript loop through the hashtables/elements in the order they are declared? Is there a browser which doesn\'t do it in order?
The object
The elements of an object that for/in enumerates are the properties that don't have the DontEnum flag set. The ECMAScript, aka Javascript, standard explicitly says that "An Object is an unordered collection of properties" (see http://www.mozilla.org/js/language/E262-3.pdf section 8.6).
It's not going to be standards conformant (i.e. safe) to assume all Javascript implementations will enumerate in declaration order.
Iteration order is also confused with respect to deleting of properties, but in this case with IE only.
var obj = {};
obj.a = 'a';
obj.b = 'b';
obj.c = 'c';
// IE allows the value to be deleted...
delete obj.b;
// ...but remembers the old position if it is added back later
obj.b = 'bb';
for (var p in obj) {
alert(obj[p]); // in IE, will be a, bb, then c;
// not a, c, then bb as for FF/Chrome/Opera/Safari
}
The desire for changing the spec to fix the iteration order seems to be quite a popular desire among developers if the discussion at http://code.google.com/p/v8/issues/detail?id=164 is any indication.
Quoting John Resig:
Currently all major browsers loop over the properties of an object in the order in which they were defined. Chrome does this as well, except for a couple cases. [...] This behavior is explicitly left undefined by the ECMAScript specification. In ECMA-262, section 12.6.4:
The mechanics of enumerating the properties ... is implementation dependent.
However, specification is quite different from implementation. All modern implementations of ECMAScript iterate through object properties in the order in which they were defined. Because of this the Chrome team has deemed this to be a bug and will be fixing it.
All browsers respect definition order with the exception of Chrome and Opera which do for every non-numerical property name. In these two browsers the properties are pulled in-order ahead of the first non-numerical property (this is has to do with how they implement arrays). The order is the same for Object.keys
as well.
This example should make it clear what happens:
var obj = {
"first":"first",
"2":"2",
"34":"34",
"1":"1",
"second":"second"
};
for (var i in obj) { console.log(i); };
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"
The technicalities of this are less important than the fact that this may change at any time. Do not rely on things staying this way.
In short: Use an array if order is important to you.