2006-06-11
Associative Arrays and Javascript
Andrew Dupont has a post about Associative Arrays in Javascript. He makes the good point that you shouldn't use the Array object for this functionality, instead use 'Object'.
Unfortunately using 'Object' has its own set of pitfalls. Try the following code in your favourite Javascript implementation:
var x = {}
x["toString"]
This will display details on the toString method on 'Object'. So we can't use a plan Object as an associative array as it has some default entries in it already obtained from its prototype.
This can be worked around by using the Javascript standard function 'hasOwnProperty'. So you could write a simple Hashtable object with a 'get' method that does:
function Hashtable() { }
Hashtable.prototype.get = function(key) {
if(this.hasOwnProperty(key))
return this[key];
else
throw "No such key";
}
Now the following code works:
var x = new Hashtable();
x.get("toString");
=> uncaught exception: No such key
x["blah"] = 5;
x.get("blah");
=> 5
It has a subtle bug too though. This breaks:
x["get"] = 5;
x.get("get");
=> TypeError: x.get is not a function
Oops, we overwrote our 'get' method. So the Hashtable object really needs to store its data in an internal object:
function Hashtable() { this.table = new Object }
Hashtable.prototype.get = function(key) {
if(this.table.hasOwnProperty(key))
return this.table[key];
else
throw "No such key";
}
Hashtable.prototype.put = function(key, value) {
this.table[key] = value;
}
The following code now works as expected:
var x = new Hashtable();
x.put("get", 5);
x.get("get");
=> 5
x.get("toString");
=> uncaught exception: No such key
The trap of using a basic Object as an associative array is seductive but as you can see it has pitfalls. They are easy to work around but it's easy to forget. Dojo's current implementation of Dictionary (as of 0.3) has this problem for example. There's a thread on the mailing list at the moment about fixing it (raised by me).