See discussions on Reddit
In JavaScript, objects are handy. They allow us to easily group multiple pieces of data together. After ES6, we got a new addition to the language - Map
. In a lot of aspects, it seems like a more capable Object
with a somewhat clumsy interface. However, most people still reach for objects when they need a hash map and only switch to using Map
when they realize the keys can't just be strings for their use cases. As a result, Map
remains underused in today's JavaScript community.
In this post, I will break down all the reasons when you should consider using Map
more and its performance characteristics with benchmarks.
In JavaScript, Object is a pretty broad term. Almost everything can be an object, except for two bottom types -
null
andundefined
. In this blog post, Object only refers to plain old objects, delimited by a left brace{
and a right brace}
.
TL;DR:
- Use
Object
for records where you have a fixed and finite number of properties/fields known at author time, such as a config object. And anything that is for one-time use in general. - Use
Map
for dictionaries or hash maps where you have a variable number of entries, with frequent updates, whose keys might not be known at author time, such as an event emitter. - According to my benchmarks, unless the keys are strings of small integers,
Map
is indeed more performant thanObject
on insertion, deletion and iteration speed, and it consumes less memory than an object of the same size.
Why Object
falls short of a hash map use case
Probably the most obvious downside of using objects for hash maps is that objects only allow keys that are strings and symbols. Any other types will be implicitly cast to string via the toString
method.
const foo = [];
const bar = {};
const obj = { [foo]: 'foo', [bar]: 'bar' };
console.log(obj); // {"": 'foo', [object Object]: 'bar'}
More importantly, using objects for hash maps can cause confusion and security hazards.
Unwanted inheritance
Before ES6, the only way to get a hash map is by creating an empty object.
const hashMap = {};