A reader from San Mateo writes:
I expected this to print the words of my phrase in order. It did not. What gives?
lzx> words = "The quick brown fox".split(" ")
«Array(4)#55| [The, quick, brown, fox]»
lzx> for (var w in words) Debug.write(words[w]);
fox
brown
quick
The
Gentle reader,
for in
iterates over the ‘keys’ of an object. An array is just an object that happens to have (mostly) numbers as keys (and auto-maintains a length
property that is one larger than the largest numeric key).
An object is just a hash table, and there is no implicit order of elements of a hash table (Java has LinkedHashMap
which preserves entry order for iteration, and TreeMap
which sorts entry order for iteration, but Javascript is a simpler language).
If you want to iterate over an array’s entries in order, use for (var i = 0; i < array.length; i++)
.
lzx> for (w = 0; w < words.length; w++) Debug.write(words[w]);
The
quick
brown
fox
If you want to iterate over an object’s keys in a particular order, you have to pull the keys out into an array, sort that array, and then iterate over that array:
var keys = new Array();
foreach (var k in array) { keys.push(k); }
keys.sort(function (a, b) {
return (a > b) - (a < b);
});
for (var i = 0; i < keys.length; i++) {
Debug.format("%s -> %s\n", keys[i], array[keys[i]]);
}
The fact that any particular runtime iterates over object keys in any particular order reveals an implementation detail of their hashes, but if you write your code to depend on that you are setting yourself up for a fall. Most Javascript runtimes just happen to use particularly trivial hash implementations that give you the illusion the keys are iterated in order.
See also the yellow box caution here.
17:00 |
Link
|
Reply
|
Track