FlyingAura
FlyingAura

Reputation: 1601

When using Objects as maps, its keys are always converted to strings. Why?

The following code:

let user1={name: "Sam"};
let user2={name:"Tyler"};
let totalReplies={};
totalReplies[user1]=5;
totalReplies[user2]=42;
console.log(totalReplies[user1]);
console.log(totalReplies[user2]);

Generates the output:

42
42

I expected the output to be:

5
42

Reading up, I got that 'When using Objects as maps, its keys are always converted to strings'. I'm not sure if I understand what this means or why object keys are converted to strings. Either way, understanding why the output was 42 42 should help enforce this concept.

Upvotes: 0

Views: 245

Answers (4)

nils
nils

Reputation: 27214

JavaScript objects only support Strings and Symbols as keys.

In situations like this, JS coerces the object to a string value (which will be something like [object Object]).

So basically your code would amount to this:

let user1={name: "Sam"};
let user2={name:"Tyler"};
let totalReplies={};
totalReplies['[object Object]']=5;
totalReplies['[object Object]']=42;
console.log(totalReplies['[object Object]']);
console.log(totalReplies['[object Object]']);

You can learn more about coercion here: http://webreflection.blogspot.ch/2010/10/javascript-coercion-demystified.html

Solution

If you need to use objects as keys in ES6+, you can use Maps instead of objects as data storage:

let user1={name: "Sam"};
let user2={name:"Tyler"};
let totalReplies = new Map();
totalReplies.set(user1, 5);
totalReplies.set(user2, 42);
console.log(totalReplies.get(user1));
console.log(totalReplies.get(user2));

Upvotes: 5

Dario
Dario

Reputation: 4035

According with ECMAscript standard, object property names can be either an identifier name (i.e. identifiers + reserved words), a string literal, or a numeric literal.

In your case user1 and user2 are objects, and converted into string they return both "[object Object]" this explain your output.

If you want to you use an object (or any primitive value) as map key, you can use the native Map object included in ES6 standard.

Upvotes: 2

Misters
Misters

Reputation: 1347

And they are actually:

var ob = {};
console.log(ob.toString())// prints "[object Object]"

What is does is that the method toString of each object is execute and the result is the same [object Object] and since you are adding the same key twice, the index assigned gets overriden by the new value.

Upvotes: 0

Jeremy Thille
Jeremy Thille

Reputation: 26390

totalReplies[user1]=5 means totalReplies[{name: "Sam"}]=5 and it makes no sense. The key is always a string, not an object.

You want totalReplies[user1.name]=5;

Upvotes: 0

Related Questions