jsguides

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

ParameterTypeDefaultDescription
iterableIterableundefinedAn 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 size property 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

FeatureMapObject
Key typesAnyStrings/Symbols
Size.size propertyManual counting
IterationIterable by defaultObject.keys() needed
OrderGuaranteed insertion orderES2015+ guarantees
Default keysNone__proto__
PerformanceBetter for frequent changesBetter 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.

See Also