Q&A
Using the Map data structure in ES6
Overview
Before ES6, developers used plain objects ({}) as maps, but objects have limitations: keys are coerced to strings, there's no clean size property, and they carry inherited prototype keys. ES6's Map is a dedicated key-value structure that fixes these issues and is optimized for frequent insertions and deletions.
graph TD
A[Map] --> B[Keys: ANY type<br/>objects, functions, primitives]
A --> C[Preserves insertion order]
A --> D[.size property]
A --> E[Directly iterable]
A --> F[Methods: set/get/has/delete/clear]
style A fill:#1e1b4b,color:#fff
Creating and Basic Operations
const map = new Map();
map.set("name", "Ada"); // string key
map.set(42, "the answer"); // number key
const objKey = { id: 1 };
map.set(objKey, "object as key"); // object key!
map.get("name"); // "Ada"
map.get(objKey); // "object as key"
map.has(42); // true
map.size; // 3
map.delete("name"); // true (removes it)
map.clear(); // empties the map
Chaining works because set returns the map: map.set("a",1).set("b",2);
Initialize from an Array of Pairs
const map = new Map([
["one", 1],
["two", 2],
["three", 3],
]);
map.get("two"); // 2
Iteration (preserves insertion order)
for (const [key, value] of map) {
console.log(key, value);
}
map.forEach((value, key) => console.log(key, value));
[...map.keys()]; // ['one', 'two', 'three']
[...map.values()]; // [1, 2, 3]
[...map.entries()]; // [['one',1], ['two',2], ['three',3]]
Map is directly iterable, and iteration order is the order keys were inserted.
Map vs Plain Object
| Feature | Map |
Object {} |
|---|---|---|
| Key types | Any (objects, functions, NaN…) | Strings & Symbols only |
| Order | Guaranteed insertion order | Mostly ordered (with caveats) |
| Size | map.size |
Object.keys(obj).length |
| Iteration | Directly iterable | Needs Object.keys/entries |
| Prototype keys | None (no accidental keys) | Inherits from Object.prototype |
| Performance | Better for frequent add/remove | Fine for fixed/record-like data |
| JSON | Not directly serializable | Native JSON.stringify |
Use a Map for dynamic dictionaries, non-string keys, frequent insertions/deletions, or when order and size matter. Use an object for fixed-shape records and when you need JSON serialization.
Converting Between Map and Object/Array
const obj = Object.fromEntries(map); // Map → object
const back = new Map(Object.entries(obj)); // object → Map
const arr = [...map]; // Map → array of [k,v] pairs
A Note on WeakMap
WeakMap is a related structure whose keys must be objects and are held weakly - entries are garbage-collected when the key object is no longer referenced. It's used for private data and caches without causing memory leaks, but it's not iterable and has no .size.
Why This Matters in Interviews
JS interviews use Map to test knowledge beyond plain objects. Key points: keys can be any type (the headline advantage), insertion order is guaranteed, .size vs Object.keys().length, direct iterability, and the absence of prototype-key pitfalls. Knowing when to choose Map vs object (dynamic keyed data vs JSON-friendly records) and mentioning WeakMap for memory-safe caches signals depth.
Common Pitfalls
- Using
map[key]instead ofmap.get(key)(bracket access sets a property, not a map entry!). - Expecting
JSON.stringify(map)to serialize entries (it produces{}); convert withObject.fromEntriesfirst. - Forgetting object keys are compared by reference (
map.get({id:1})won't find an entry set with a different{id:1}object). - Using a plain object when non-string keys or guaranteed order are needed.