I just ran into a tricky gotcha in JavaScript.
I was trying to store some objects in an associative array. Based on my experience with Java, Ruby, and other languages, I expected that given code like this:
1 2 3 4 5 6 7 |
var dictionary = {}; var obj1 = {}; var obj2 = {}; dictionary[obj1] = 'foo' dictionary[obj2] = 'bar' |
The result of dictionary[obj1] would be ‘foo’ and dictionary[obj2] would be ‘bar’.
This is not the case!
The problem is that JavaScript objects are not really hash tables. They’re associative arrays, and the key can only be a String. When you insert an object into a associative array, toString() is called and that is used as the key. Unfortunately, the default toString implementation for JavaScript objects returns “[object Object]”...which is not only very unhelpful when debugging, but doesn’t provide you with a unique key for your associative array.
You can work around this problem by overriding toString. Or you can figure out another way to associate your object with a value. D’oh!


i would have made the exact same assumption. thanks for sharing. you may have just saved me a couple of hours of debugging in the future.
Why not associate the value with the object instead?
dictionary[‘foo’] = obj1;
Trying to treat associative arrays as hash tables, is going to be like forcing square pegs through round holes. Embrace javascript instead of fighting it.
You could also write your code like this:
or even
why should dictionary store different values for equal objects?
obj1 == obj2 => dictionary[obj1] is the same as dictionary[obj2]
@Linuxdan: I didn’t go into it in the example but the reason is because I was receiving the object as an argument in a callback and needed to know what path the object was associated with.. I could not look up the object the other way because I didn’t know what the key would be. (And yes, there’s a reason I couldn’t add a method to the object: it is an Adobe AIR application and the class is not extendable.)
@Morgan: thanks I know that. I was simplifying a larger example.
@keymone: the objects in the real code weren’t == in the sense I would expect from Ruby or Java. They were different instances of the same class, which had undifferentiated output from toString. This behavior was unexpected by me, so I wrote it up.
Cool catch—like jb, this would have bitten me in the arse one day and I’d have wasted time debugging it.
Is this part of the language standard, or a particular implementation?
@Joe: I’m pretty sure that’s just how the language works. This happened to me using Adobe AIR, which uses WebKit.
There are work-arounds you could use if you were in a pure-JavaScript environment (like overriding toString) but AIR has classes from Flash that you can’t change.
Technically they aren’t even hashes, they are objects. Note:
var foo = {}; foo[‘bar’] = ‘baz’; console.log(foo.bar);
I think that’s because javascript doen’t have hashes or associative arrays. That value that you’re providing in the square brackets is a property name… javascript uses the “dot notation” and the “associative array notation” interchangeably. So of course it has to be a string…. Or at least, that’s how I understand it.