spacer spacer spacer


Order in the code

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]); 

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]); 

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