Map
is an ECMAScript 2015 feature that allows storing key-value pairs in a collection, similar to plain objects, but with a few “advantages” such as:
- The keys can be of any type, not just strings (even other
Map
s). - The keys are ordered.
- It includes a bunch of methods to manipulate the collection.
It is a great tool but, sadly, an overly used one, and more often than not, it can or should be replaced by a plain object or an array.
Data interchange and serialization
I wrote this first because, from my point of view, this is one of the most important reasons to avoid Map
. One of the main advantages of using plain objects in JavaScript is that we can easily convert them to and from JSON. However, we can’t serialize Map
as JSON, nor can we parse it from JSON directly. This limitation means we need to use extra steps or libraries to handle Map
when working with JSON data.
For example, if we have a Map
object like this:
We cannot simply use JSON.stringify
to convert it to JSON:
Instead, we need to convert the Map object to an array of key-value pairs first:
Similarly, if we have a JSON string like this:
We cannot simply use JSON.parse
to convert it to a Map
object:
Instead, we need to pass the parsed Array
to the Map
constructor:
These extra steps are cumbersome, verbose, and prone to errors and inconsistencies. For example, if we have nested Maps or other non-serializable values in our Map object, we must handle them separately or use custom replacer and reviver functions.
On the other hand, plain objects can be easily serialized and parsed as JSON without any extra steps or libraries:
So this makes plain objects much more convenient and reliable for working with data serialization.
Reading data from a Map
Another disadvantage of using Map objects is that they have a different syntax for accessing values than plain objects. To get a value from a Map object by its key, we need to use the get method:
However, to get a value from a plain object by its key, we can use dot notation or bracket notation:
This is picky, until we consider that we also need to write stuff like deconstructing differently:
Or if we want to get more than one value:
And for spread syntax:
We are sacrificing a lot of readability and consistency just for the sake of using Map
.
Creating a Map
Staying on the topic of syntax, creating a new Map
with data on it is also less readable than creating a plain object:
Meanwhile, to create a new plain object, we can use curly braces and comma-separated key-value pairs:
The performance
I’m not a person that usually makes this argument. I would take something readable over something performant any day. But in this case, we have already proven that readability could be better, and performance could be better too. This point is not a surprise if we compare plain objects with objects that include methods (set
, get
, has
, etc.) and state (size
, the key-value pairs, etc.).
Of course, there may be some cases where Maps have better performance than plain objects, such as when using non-string keys or when iterating over extensive collections. However, these cases are rare and specific and do not justify using Map
over plain objects in general.
Immutability
Map
favors mutation. We can work with “immutable Map
,” but then the performance suffers even more. So when working with architectures based on immutability, such as React, Map
becomes even less compelling. I already wrote about the problems introduced by mutation and how to avoid them, so I’ll no go into details. We can achieve an immutable Map
, but for that to be performant, we need libraries such as Immer, and at that point, we are just adding even more complexity to our code.
The sorting argument
One common argument favoring Map
is that it has ordered key-value pairs, while plain objects can’t guarantee that. However, my point generally is: If we are concerned about order, we have an object in JavaScript already for that, and we have had it for a long time, and it’s called Array
.
Conclusion
For the most part, we can replace Map
with plain objects and get the same results with less and more readable and maintainable code with better performance.
Map
has its uses. It can be an excellent tool for handling some types of structures in memory in some scenarios, but my rule of thumb generally is to use it only when we need to use non-string keys for some reason (tho, more often than not, an array of tuples are good enough).