> From: pete higgins
> 
> About anything can be a key in JS. (DomNodes can't, though 
> btw, but functions objects etc)

No, that isn't true, sorry.

Object keys in JavaScript are strings only, nothing else.

> var bar = { a:"b", c:"d" };
> var bar2 = [1,2,3,4];
> var foo = {};
> foo[bar] = "baz";
> foo[bar2] = "baz2";
> 
> if(bar in foo){ console.log(foo[bar]); } // baz
> if(bar2 in foo){ console.log(foo[bar2]); } // baz2

What you're observing is that JS will convert any object to a string when
necessary, by calling that object's toString() method.

The reason your example works is that the two properties you're adding have
different string representations, because one is an object and the other is
an array. Let's look at it more closely:

  var bar = { a:"b", c:"d" };
  var bar2 = [1,2,3,4];
  var foo = {};
  foo[bar] = "baz";
  foo[bar2] = "baz2";

  for( var key in foo ) { console.log( typeof key, key ); }
  // string [object Object]
  // string 1,2,3,4

Now try it with two different *object* keys instead of an object and an
array

  var bar = { a:"b", c:"d" };
  var bar2 = { w:"x", y:"z" };
  var foo = {};
  foo[bar] = "baz";
  foo[bar2] = "baz2";

  for( var key in foo ) { console.log( typeof key, key, foo[key] ); }
  // string [object Object] baz2 (only one - oops!)

Because bar and bar2 have identical string representations - '[object
Object]' - only one property is added to the foo object.

DOM nodes do work the same way - because they also have string
representations. But you'll run into the same problem, because, for example,
every DIV has the same string representation '[object HTMLDivElement]'.

As another example, here's an object with a custom toString method. Note
that after adding the property, we can reference it using the name that
toString returned:

  a = { toString:function() { return 'foo'; } };
  b = {};
  b[a] = 'test';
  console.log( b.foo );  // 'test'

And one with *no* toString method:

  a = { toString:null };
  b = {};
  b[a] = 'test';  // TypeError: can't convert a to string

All this is quite different from, say, Ruby, where any object *can* be used
as a hash key:

  irb(main):001:0> a = { 'a' => 'b', 'c' => 'd' }
  => {"a"=>"b", "c"=>"d"}
  irb(main):002:0> b = { 'a' => 'b', 'c' => 'd' }
  => {"a"=>"b", "c"=>"d"}
  irb(main):003:0> c = { a => 'aaa', b => 'bbb' }
  => {{"a"=>"b", "c"=>"d"}=>"bbb", {"a"=>"b", "c"=>"d"}=>"aaa"}
  irb(main):004:0> c[a]
  => "aaa"
  irb(main):005:0> c[b]
  => "bbb"

Note that the a and b hashes are two distinct objects even though their
content is similar, and each one can be used as a separate hash key.

-Mike

> From: pete higgins
> 
> About anything can be a key in JS. (DomNodes can't, though 
> btw, but functions objects etc)
> 
> var bar = { a:"b", c:"d" };
> var bar2 = [1,2,3,4];
> var foo = {};
> foo[bar] = "baz";
> foo[bar2] = "baz2";
> 
> if(bar in foo){ console.log(foo[bar]); } // baz
> if(bar2 in foo){ console.log(foo[bar2]); } // baz2

Reply via email to