JavaScript Maps vs Plain JavaScript Objects

Software developer since 2004. Web/front-end expert (HTML, CSS, JS). O'Reilly and Apress author. Freelance tech writer. Blogger. Bridging code and communication in tech.
Search for a command to run...

Software developer since 2004. Web/front-end expert (HTML, CSS, JS). O'Reilly and Apress author. Freelance tech writer. Blogger. Bridging code and communication in tech.
No comments yet. Be the first to comment.
Using semantic HTML elements has several benefits over using plain divs.

Vibe coding is a new way to code that is gaining popularity. But is it the future?

Looking back on my journey as a published author, from Apress to O'Reilly.

Learn how to use media queries to learn about certain device settings.

You’re working on a bug fix and find some bad code that causes a bug. The git blame command will tell you who the last developer was that modified that line, and when they modified it. But what if you don’t know what code introduced the bug? For thes...

ES2015, also known as ES6, added lots of new things to the JavaScript language. One very useful addition was the Map. Map allows you to map keys to values.
You might be thinking - we already could map keys to values in JavaScript!
const map = {};
map[key1] = value1;
map[key2] = value2;
You would be correct. Prior to ES2015, you could absolutely use JavaScript objects to map keys to values. However, there was an important limitation. When mapping with a JavaScript object, only strings may be used as keys. Consider the following:
const map = {};
const key1 = { foo: 'bar' };
const key2 = { baz: 'qux' };
map[key1] = 100;
map[key2] = 200;
Here we are taking two JavaScript objects and mapping them to some numbers. This is perfectly valid JavaScript; you won't get any errors when running this code. Let's see what happens when we try to retrieve these values:
console.log(map[key2]); // prints 200
So far, so good. Now let's look up the first key:
console.log(map[key1]); // also prints 200
Why does this print 200, when in the above code we mapped key1 to the value 100? Let's investigate by looking at all the keys in the object map:
console.log(Object.keys(map));
This will print out an array with a single key:
["[object Object]"]
What's going on here?
It turns out, if you use a non-string key in a JavaScript object, the key is converted to a string by calling toString on it. For a plain JavaScript object, this results in the key '[object Object]'.
So when we set the first key in our map object, it was converted to that string, and everything would have worked as expected up to that point. However, when we added the second key, that was also converted to the same string value, so it overwrote the previous mapping. This is why the result will always be 200.
Map to the rescueThe ES2015 Map can solve this problem for us. Like a plain object, it can map keys to values. Unlike plain objects, a Map can have non-string keys.
MapLet's use the same example as above, only using a Map instead of a plain JavaScript object.
const map = new Map();
const key1 = { foo: 'bar' };
const key2 = { baz: 'qux' };
map.set(key1, 100);
map.set(key2, 200);
console.log(map.get(key1)); // prints 100
console.log(map.get(key2)); // prints 200
Now the mapping works as expected, because a Map can use objects as keys.
For more information about Map, see the excellent MDN documentation.