1

1) I am trying to add a sequence of key-value pairs to a JS plain object, where the key itself is an object. Each time I add a key-value pair, the object is overwritten (see live here).

var x = {};

var y = {
  'name': 'cat',
  'note': 'lazy animal'
}
var yy = 'meow'

x[{
  'name': 'dog',
  'note': 'loyal animal'
}] = 'bhow'
x[y] = yy

for(var k in x) {
  console.log(k);
  console.log(x[k]);
}

Console Output:

"[object Object]"
"meow"

2) This (overwriting behavior) does not happen when the key is a string (see live here).

var x = {};

var y = 'cat'
var yy = 'meow'

x['dog'] = 'bhow'
x[y] = yy

for(var k in x) {
  console.log(k);
  console.log(x[k]);
}

Console Output:

"dog"
"bhow"
"cat"
"meow"

Would like to understand why this is happening?

I figured our some solutions by going through the other questions (here). But I am unable to grasp the concept here. Any guidance will be much appreciated.

Community
  • 1
  • 1
  • 3
    You can't. Object keys can only be strings or symbols. You want a Map. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map – Jared Smith Jun 14 '16 at 15:56
  • Object keys should be strings. Moreover, you are not specifying the same keys in the second example, so obviously there won't be any overwriting? – Mohit Bhardwaj Jun 14 '16 at 15:57

2 Answers2

0

Object keys have to be strings (or symbols), so when you try to use an object as a key, it first converts it to a string representation, which you've seen is "[object Object]".

You can however do what you wish to do by overriding the toString function on your objects, and as long as you return a unique string for each object (perhaps as a hash of the object's contents), your code will work as expected, as it will use that toString function to obtain the string representation of your object, and use that as the key:

var x = {};

var y = {
  'name': 'cat',
  'note': 'lazy animal',
  toString: function() {
    return 'yobj';
  }
};
var yy = 'meow';

x[{
  'name': 'dog',
  'note': 'loyal animal',
  toString: function() {
    return 'xobj';
  }
}] = 'bhow';
x[y] = yy;

for (var k in x) {
  console.log(k);
  console.log(x[k]);
}

As Jared mentions in his comment, the Map object (introduced with ES6 last year) is in part designed to solve this problem, and allows you to use objects directly as your keys if you're running in an environment that supports its use.

Community
  • 1
  • 1
James Thorpe
  • 31,411
  • 5
  • 72
  • 93
0

Any time you pass something to the property accessor of an object (the object[...] syntax), it gets converted to a string (see here under "Property names").

Plain Javascript objects like those you're using are typecasted to strings using the default toString() method which simply returns "[object Object]". That's why they both end up pointing to the same value.

ttzn
  • 2,543
  • 22
  • 26