14

I read a few questions and answers about javascript dictionary implementations, but they don't meet my requirements:

  • the dictionary must be able to take objects as keys
  • the values must be accessible by the []-operator

So i came up with the idea to overwrite the "valueOf"-method in Object.prototype, as follows:


   Object.__id__ = 0;
   Object.prototype.valueOf = function() {
      if(!this.__id__)
         this.__id__ = ++Object.__id__;
       return "__id__" + this.__id__;
   }
   Object.prototype.toString = Object.prototype.valueOf;

   //test   
   var x = {p1: "5"};
   var y = [6];
   var z = {};
   z[x] = "7";
   z[y] = "8";
   console.log(z[x], z[y]);

I tested this with google-chrome and it seems to work well, but I'm a bit skeptical, whether this will cause some drawbacks, since it was so easy to implement.

Considering that the valueOf method is not used for other purposes in the whole code, do you think there are any disadvantages?

fishbone
  • 2,706
  • 2
  • 30
  • 43

3 Answers3

6

It's an interesting idea. I suggest my jshashtable. It meets your first requirement but not the second. I don't really see the advantage of insisting on using the square bracket property access notation: do you have a particular requirement for it?

With jshashtable, you can provide a hashing function to the Hashtable constructor. This function is passed an object to be used as a key and must return a string; you could use a function not dissimilar to what you have there, without having to touch Object.prototype.

There are some disadvantages to your idea:

  1. Your valueOf method will show up in a for...in loop over any native object;
  2. You have no way determining which keys should be considered equal, which is something you may want to do. Instead, all keys will be considered unique.
  3. This won't work with host objects (i.e. objects provided by the environment, such as DOM elements)
Tim Down
  • 292,637
  • 67
  • 429
  • 506
  • I always used your library before and it works well. But currently I'm working on a ActionScript 3 to Javascript converter. AS3 provides a Dictionary. If i use your library, I would need to check the types and replace brackets with get/set. The valueOf doesn't appear in for...in if I use Object, but it appears if I define a new "class". (Maybe this behaviors differently in other browsers). Since i don't like to overwrite Object.prototype.valueOf itself you answered my question – fishbone Jul 27 '10 at 19:14
2

It is an interesting question, because I had so far assumed that any object can be used as an index (but never tried with associative arrays). I don't know enough about the inner workings of JavaScript to be sure, but I'd bet that valueOf is used somewhere else by JavaScript, even if not in your code. You might run into seemingly inexplicable problems later. At least, I'd restrict myself to a new class and leave Object alone ;) Or, you explicitly call your hashing function, calling it myHash() or whatever and calling z[x.myHash()] which adds clutter but would let me, personally, sleep better ;) I can't resist thinking there's a more JavaScript-aware solution to this, so consider all of these ugly workarounds ;)

Nicolas78
  • 5,027
  • 1
  • 21
  • 38
0

If you came upon this question looking for a JS dictionary where objects are keys look at Map Map vs Object in JavaScript

Ivan Koshelev
  • 2,691
  • 2
  • 20
  • 37