Map
new Map() The Map object holds key-value pairs and remembers the original insertion order of its keys. Unlike plain JavaScript objects, Map keys can be of any type—strings, numbers, objects, or even NaN.
Syntax
new Map()
new Map(iterable)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
iterable | Iterable | undefined | An array or other iterable whose elements are key-value pairs (e.g., [[key1, value1], [key2, value2]]) |
Return value
A new Map instance. When called with an iterable, the constructor populates the collection from the provided entries before returning.
The examples below cover the three main ways to put data into a Map — building it entry by entry with set(), seeding it from an iterable at construction time, and using object references as keys.
Examples
Creating and populating a Map
const userRoles = new Map();
userRoles.set('alice', 'admin');
userRoles.set('bob', 'editor');
userRoles.set('charlie', 'viewer');
console.log(userRoles.get('alice'));
// admin
console.log(userRoles.has('bob'));
// true
console.log(userRoles.size);
// 3
You can also seed a Map directly from an iterable of [key, value] pairs at construction time. This is cleaner than calling set() repeatedly when the data already exists in array form. The constructor accepts any iterable — arrays of pairs, another Map, or the result of Object.entries().
Initializing with an iterable
const config = new Map([
['theme', 'dark'],
['language', 'en'],
['notifications', true]
]);
for (const [key, value] of config) {
console.log(`${key}: ${value}`);
}
// theme: dark
// language: en
// notifications: true
One of Map’s defining advantages is that keys are not limited to strings and symbols. You can use objects, functions, or any other value as a key. Object keys are compared by reference, not by structural equality, which makes Map the natural choice for associating metadata with specific object instances — DOM nodes, request objects, or any heap-allocated entity.
Using objects as keys
const cache = new Map();
const obj = { id: 1 };
cache.set(obj, 'cached value');
console.log(cache.get(obj));
// cached value
The following patterns show how Map interacts with plain objects — converting back and forth, and using the collection to count occurrences. These are the operations you reach for most often when moving data between object-shaped APIs and Map-shaped logic.
Common Patterns
Converting from an object
const obj = { a: 1, b: 2, c: 3 };
const map = new Map(Object.entries(obj));
console.log(map.get('a'));
// 1
The reverse conversion is just as direct. Object.fromEntries() accepts any iterable of [key, value] pairs — including a Map — and produces a plain object. This is the bridge you use when an API expects a POJO or when you need JSON.stringify to work on the data.
Converting to an object
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
const obj = Object.fromEntries(map);
console.log(obj);
// { a: 1, b: 2, c: 3 }
Counting occurrences is a classic Map use case. The get() / set() loop with a fallback of 0 is concise and avoids the if (!map.has(key)) guard that object-based counters would require. Each unique item becomes a key, and each set() increments the tally.
Counting occurrences
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const counts = new Map();
for (const fruit of fruits) {
counts.set(fruit, (counts.get(fruit) || 0) + 1);
}
console.log(counts);
// Map(3) { 'apple' => 3, 'banana' => 2, 'orange' => 1 }
When to use Map
Use Map when you need:
- Keys that are not strings (objects, numbers, etc.)
- A guaranteed insertion order
- A
sizeproperty for easy counting - Frequent additions and deletions
- Iteration in a predictable sequence
Use a plain object when:
- Keys are only strings or symbols
- You need JSON serialization
- The data is relatively static
- You want prototype inheritance
Map vs Object
| Feature | Map | Object |
|---|---|---|
| Key types | Any | Strings/Symbols |
| Size | .size property | Manual counting |
| Iteration | Iterable by default | Object.keys() needed |
| Order | Guaranteed insertion order | ES2015+ guarantees |
| Default keys | None | __proto__ |
| Performance | Better for frequent changes | Better for static data |
Map iteration order
Map guarantees that iteration follows insertion order — always. This is unlike plain objects, where the order of string keys is implementation-defined (though modern engines follow insertion order in practice for non-integer keys). When you use for...of, map.forEach(), map.keys(), map.values(), or map.entries(), entries appear in the order they were added with set(). If you delete a key and re-add it, it moves to the end of the iteration order.
Map and memory management
Unlike WeakMap, a Map holds strong references to both its keys and its values. As long as the Map itself is alive, all keys and values it holds are kept in memory and cannot be garbage collected. For caching patterns where the key might outlive its usefulness, a WeakMap is more appropriate — it lets the key be garbage collected when nothing else references it, automatically removing the entry.
Converting between Map and object
Object.fromEntries(map) converts a Map to a plain object in a single call. The reverse is new Map(Object.entries(obj)). These conversions are useful when interfacing with APIs that expect plain objects (like JSON.stringify) or when you want the benefits of Map (any key type, guaranteed order, size property) while starting from existing object data.
const map = new Map([['a', 1], ['b', 2]]);
JSON.stringify(Object.fromEntries(map)); // '{"a":1,"b":2}'
Browser and Node.js support
Map is supported in all modern browsers and Node.js 0.12+. For older environments, use a polyfill or fallback to a plain object with a custom implementation.