A JavaScript object has always doubled as a dictionary, and that holds as long as the keys are strings. The day you need to attach data to a date, to an element on the page or to another object, it stops keeping up.
Map is the structure built for that job: a collection of key-value pairs where the key can be anything at all.
Definition
A Map is an ordered collection of key-value pairs. Unlike an Object, it accepts any value as a key, keeps insertion order and exposes its size directly.
const carts = new Map();
const customer = { id: 7 };
carts.set(customer, ["keyboard"]);
carts.set("total", 89);
console.log(carts.get(customer)); // [ 'keyboard' ]
console.log(carts.has("total")); // true
console.log(carts.size); // 2The customer key is an object, and it is that exact object that acts as the key: a copy carrying the same properties would find nothing. The useful methods come down to five names: set, get, has, delete, clear.
Compared with a plain object
| Point | Map | Object |
|---|---|---|
| Keys accepted | Any value at all | Strings and symbols |
| Size | size | Count the keys |
| Order | Insertion order | Integer keys first |
| Inherited keys | None | constructor and friends |
That last row matters more than it looks. On a plain object, "constructor" in data is true even though nobody wrote that key, which is enough to skew a membership test on keys coming from outside. A Map only knows what was put into it.
Walking through it and converting it
const stock = new Map([
["keyboard", 12],
["mouse", 0],
]);
for (const [item, quantity] of stock) {
console.log(item, quantity);
}
console.log([...stock.keys()]); // [ 'keyboard', 'mouse' ]
console.log(JSON.stringify(stock)); // {}
console.log(JSON.stringify([...stock])); // [["keyboard",12],["mouse",0]]A Map is walked directly with of, each pass handing over a pair ready to be pulled apart by Destructuring.
The second-to-last line is the classic trap: JSON knows nothing about Map objects and serializes an empty object, with no warning whatsoever. You have to go through an array of pairs, using Spread (...) or Array.from.
Frequently asked questions
When should a plain object stay?
Whenever the keys are known upfront and few, like a four-field record. The object destructures, serializes to JSON with no effort and reads better. A Map earns its place once the keys show up at runtime or are not strings.
Are keys compared the way === compares?
Almost. The comparison in use treats NaN as equal to itself, which Strict equality (===) refuses: a NaN key can therefore be found again. The only other difference is that -0 and 0 count as the same key.
What is a WeakMap for?
For attaching data to objects without keeping them alive in memory. Its keys must be objects and cannot be walked through. It is the tool behind caches tied to a page element, which vanish along with it.