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
This does not answer the question per se, but offers a solution to the basic problem.
Assuming that you cannot rely on order to preserved, why not use an array of objects with key and value as properties?
var myArray = [
{
'key' : 'key1'
'value' : 0
},
{
'key' : 'key2',
'value' : 1
} // ...
];
Now, it is up to you to ensure that the keys are unique (assuming that this is also important to you. As well, direct addressing changes, and for (...in...) now returns indexes as 'keys'.
> console.log(myArray[0].key);
key1
> for (let index in myArray) {console.log(myArray[index].value);}
0
1
See the Pen for (...in...) addressing in order by JDQ (@JDQ) on CodePen.
As stated by other answers, no, the order is not guaranteed.
If you want to iterate in order, you can do something like:
let keys = Object.keys(myObject);
for (let key of keys.sort()) {
let value = myObject[key];
// Do what you want with key and value
}
Note that performance-wise, this is not optimal, but that's the price when you want a nice alphabetical display.
The order cannot be trusted. Both Opera and Chrome return the list of properties unordered.
<script type="text/javascript">
var username = {"14719":"A","648":"B","15185":"C"};
for (var i in username) {
window.alert(i + ' => ' + username[i]);
}
</script>
The code above shows B, A, C in Opera and C, A, B in Chrome.
Bumping this a year later...
It is 2012 and the major browsers still differ:
function lineate(obj){
var arr = [], i;
for (i in obj) arr.push([i,obj[i]].join(':'));
console.log(arr);
}
var obj = { a:1, b:2, c:3, "123":'xyz' };
/* log1 */ lineate(obj);
obj.a = 4;
/* log2 */ lineate(obj);
delete obj.a;
obj.a = 4;
/* log3 */ lineate(obj);
gist or test in current browser
Safari 5, Firefox 14
["a:1", "b:2", "c:3", "123:xyz"]
["a:4", "b:2", "c:3", "123:xyz"]
["b:2", "c:3", "123:xyz", "a:4"]
Chrome 21, Opera 12, Node 0.6, Firefox 27
["123:xyz", "a:1", "b:2", "c:3"]
["123:xyz", "a:4", "b:2", "c:3"]
["123:xyz", "b:2", "c:3", "a:4"]
IE9
[123:xyz,a:1,b:2,c:3]
[123:xyz,a:4,b:2,c:3]
[123:xyz,a:4,b:2,c:3]
in IE6, the order is not guaranteed.
From the ECMAScript Language Specification, section 12.6.4 (on the for .. in
loop):
The mechanics of enumerating the properties is implementation dependent. The order of enumeration is defined by the object.
And section 4.3.3 (definition of "Object"):
It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.
I guess that means you cant rely on the properties being enumerated in a consistent order across JavaScript implementations. (It would be bad style anyway to rely on implementation-specific details of a language.)
If you want your order defined, you will need to implement something that defines it, like an array of keys that you sort before accessing the object with it.