JavaScript Maps vs Plain JavaScript Objects

JavaScript Maps vs Plain JavaScript Objects

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.

Couldn't we already do that?

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 rescue

The 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.

Creating a Map

Let'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.