The Map collection in JavaScript
Map is a built in JavaScript object that stores key, value pairs and remembers the insertion order of those pairs. It looks like a plain object {}, but it has extra abilities: a key may be any data type, it comes with convenient methods for adding, removing and iterating, and the order of elements is guaranteed.
Theory
TL;DR
Mapis a collection of key, value pairs with a guaranteed insertion order.- A key can be anything: a string, a number, an object, a function, even
NaN. - Object keys are compared by reference, not by their string representation.
- Methods:
set,get,has,delete,clear, plus thesizeproperty. - The collection is iterable:
for...of,.forEach(),.keys(),.values(),.entries(). - Conversion works both ways:
new Map(Object.entries(obj))andObject.fromEntries(map).
Quick example
const map = new Map();
map.set('name', 'Alex');
map.set('age', 25);
console.log(map.get('name')); // Alex
console.log(map.get('age')); // 25
console.log(map.size); // 2Core methods and properties
| Method / property | What it does | Example |
|---|---|---|
set(key, value) | Adds an entry | map.set('a', 1) |
get(key) | Returns the value for a key | map.get('a') |
has(key) | Checks whether a key exists | map.has('a') // true |
delete(key) | Removes an entry | map.delete('a') |
clear() | Empties the whole collection | map.clear() |
size | Number of entries | map.size // 2 |
set() returns the Map itself, so calls can be chained: map.set('a', 1).set('b', 2).
Keys of any type
const map = new Map();
const objKey = { id: 1 };
const funcKey = () => {};
const numKey = 42;
map.set(objKey, 'object');
map.set(funcKey, 'function');
map.set(numKey, 'number');
console.log(map.get(objKey)); // object
console.log(map.get(funcKey)); // function
console.log(map.get(42)); // numberUnlike a plain object {}, keys here are compared by reference, not by their stringified form. So { id: 1 } and a fresh literal { id: 1 } are two different keys.
Even NaN works as a key, which is impossible in plain objects:
const map = new Map();
map.set(NaN, 'Not a Number');
console.log(map.get(NaN)); // 'Not a Number'Iterating a Map
Map is an iterable collection, so you can walk it in several ways.
for...of:
const map = new Map([
['name', 'Alex'],
['age', 25],
]);
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}
// name: Alex
// age: 25- The
forEachmethod (mind the argument order: value first, key second):
map.forEach((value, key) => {
console.log(key, value);
});- Keys, values or entries separately:
console.log([...map.keys()]); // ['name', 'age']
console.log([...map.values()]); // ['Alex', 25]
console.log([...map.entries()]); // [['name','Alex'], ['age',25]]Map versus a plain object
| Feature | Object | Map |
|---|---|---|
| Key type | String or symbol only | Any type, including objects and functions |
| Order of elements | Not guaranteed (before ES2015) | Guaranteed |
| Number of entries | Counted manually (Object.keys().length) | map.size |
| Removal | delete obj.key (slow) | map.delete(key) (fast) |
| Iteration | for...in (picks up inherited properties) | Clean for...of |
| Performance | Better for small data sets | Better for frequent inserts and deletes |
Conversion and practical use
From an object to a Map:
const obj = { a: 1, b: 2 };
const map = new Map(Object.entries(obj));From a Map to an object:
const obj2 = Object.fromEntries(map);An occurrence counter, the classic case for a Map:
const arr = ['a', 'b', 'a', 'c', 'b', 'a'];
const counter = new Map();
for (const item of arr) {
counter.set(item, (counter.get(item) || 0) + 1);
}
console.log(counter); // Map(3) { 'a' => 3, 'b' => 2, 'c' => 1 }Reach for Map when:
- you need keys that are not only strings;
- insertion order matters;
- entries are added and removed often;
- you are working with associative data structures.
Short summary:
| What | Description |
|---|---|
| Type | A key, value collection |
| Keys | Any type, including objects |
| Order | Preserved |
| Methods | .set(), .get(), .has(), .delete(), .clear() |
| Size | map.size |
| Iteration | for...of, .forEach(), .keys(), .values(), .entries() |
Common mistakes
- Treating a
Maplike an object.map['name']creates a regular property on theMapobject rather than an entry in the collection, andmap.get('name')will returnundefined. - Expecting
map.length. AMaphas nolength, it hassize, and that is a property, not a method. - Using a fresh object literal as a lookup key.
map.set({ id: 1 }, x)andmap.get({ id: 1 })are different references, so the result isundefined. - Mixing up the
forEachargument order. The callback receives(value, key, map), not(key, value). - Serialising a
MapwithJSON.stringify. The result is{}; convert the collection into an object or an array first, for example withObject.fromEntries(map). - Keeping object keys in a
Mapand expecting garbage collection. AMapholds strong references; for weak ones you need aWeakMap.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.