Map.prototype.set()
map.set(key, value) The set() method adds or updates a key-value pair in a Map. If the key already exists, its value is replaced. If the key is new, a new entry is created. The method returns the Map itself, which enables method chaining.
Key comparison uses the SameValueZero algorithm: -0 and +0 are treated as the same key, and NaN is equal to itself. This differs from object properties, which only support string and symbol keys. Maps accept any value — objects, functions, null, and primitives — as keys.
Syntax
map.set(key, value)
Parameters
| Parameter | Type | Description |
|---|---|---|
| key | any | The key to set |
| value | any | The value to associate with the key |
Return value
The Map itself, allowing chained calls.
The examples below walk through set() from basic insertion up through caching and conditional updates. Each one isolates a specific behaviour — overwriting, chaining, non-string keys, and value accumulation — so you can see when set() solves a problem more cleanly than plain object property assignment.
Examples
Basic usage
const userRoles = new Map();
userRoles.set('alice', 'admin');
userRoles.set('bob', 'editor');
console.log(userRoles.get('alice'));
// 'admin'
When a key already exists in the Map, calling set() replaces the associated value without changing the entry’s position in insertion order. This means you can call set() unconditionally — there is no need to guard with has() unless you explicitly want to prevent overwriting. The next example shows that behaviour.
Updating existing values
const scores = new Map();
scores.set('player1', 100);
scores.set('player1', 150); // Updates the value
console.log(scores.get('player1'));
// 150
Setting a key that already exists replaces the old value. The Map’s size does not change when you overwrite an existing key.
Because set() returns the Map itself, you can chain several calls into a single expression. Chaining keeps initialization compact — you write the variable name once and build the entire collection step by step. The next example shows how a Map can be fully populated in one statement.
Method chaining
const userRoles = new Map();
// set() returns the Map, enabling chaining
userRoles.set('alice', 'admin')
.set('bob', 'editor')
.set('charlie', 'viewer');
console.log([...userRoles.entries()]);
// [['alice', 'admin'], ['bob', 'editor'], ['charlie', 'viewer']]
Maps accept any value as a key — objects, functions, and symbols included. This is a fundamental difference from plain objects, which coerce all keys to strings. When you use objects as Map keys, comparison is by reference, not by deep equality: two distinct objects with identical properties are treated as separate keys. The next example illustrates this behaviour.
Map with object keys
const visits = new Map();
const page1 = { path: '/home', lang: 'en' };
const page2 = { path: '/home', lang: 'es' };
visits.set(page1, 1500);
visits.set(page2, 800);
console.log(visits.get(page1));
// 1500
Object keys are compared by reference, not by value. Two objects with identical properties are different keys unless they are the same object reference.
Map values are just as flexible as keys — you can store arrays, nested objects, functions, and primitives side by side. This makes a single Map suitable as an ad-hoc configuration store or a lightweight dependency container without separate data structures for each type of value. The following example puts arrays, objects, and callables into one Map.
Map with various value types
const data = new Map();
data.set('users', ['alice', 'bob']);
data.set('config', { theme: 'dark', lang: 'en' });
data.set('callback', () => console.log('ready'));
console.log(data.get('users'));
// ['alice', 'bob']
console.log(data.get('config').theme);
// 'dark'
data.get('callback')();
// 'ready'
Several recurring JavaScript patterns depend on set() as their core write operation. Memoization caches, building Maps from plain objects, and conditional counter updates all use set() to maintain state that grows or changes as the program runs. Each pattern below highlights a different way set() integrates into a larger workflow.
Common patterns
Caching with Map
function fibonacci(n, cache = new Map()) {
if (cache.has(n)) return cache.get(n);
if (n <= 1) return n;
const result = fibonacci(n - 1, cache) + fibonacci(n - 2, cache);
cache.set(n, result);
return result;
}
console.log(fibonacci(50));
// 12586269025
Object.entries() converts a plain object into an array of [key, value] pairs, which the Map constructor accepts directly. This one-liner is the standard bridge for bringing existing object data into the Map world when you need non-string keys, guaranteed insertion order, or the size property.
Building a Map from an object
const obj = { a: 1, b: 2, c: 3 };
const map = new Map(Object.entries(obj));
map.set('d', 4);
console.log(map.get('b'));
// 2
Pairing get() with set() and a fallback value lets you accumulate counts or merge nested data without an explicit has() check. This pattern is compact and avoids the extra guard clause that object-based counters would need — if the key is absent, get() returns undefined and the || operator supplies a sensible default.
Conditional updates
const inventory = new Map([
['apples', 10],
['bananas', 5]
]);
function addStock(fruit, quantity) {
const current = inventory.get(fruit) || 0;
inventory.set(fruit, current + quantity);
}
addStock('apples', 5);
addStock('oranges', 20);
console.log([...inventory]);
// [['apples', 15], ['bananas', 5], ['oranges', 20]]
The get / set pattern with a default value is a concise way to accumulate counts or totals without checking for key existence first.
Overwriting vs inserting
When you call set() with a key that already exists, the Map updates the value in place. The entry’s position in insertion order does not change — the key stays where it was inserted, not at the end. This means iterating after an update visits keys in their original order.
const m = new Map([['a', 1], ['b', 2], ['c', 3]]);
m.set('b', 99);
console.log([...m.keys()]); // ['a', 'b', 'c'] — order preserved
console.log(m.get('b')); // 99
set() vs plain object property assignment
Maps and plain objects are both key-value stores, but set() has several advantages over property assignment when the key set is dynamic or keys come from user input. Property names on objects interact with the prototype chain (a key named "constructor" or "hasOwnProperty" can shadow built-in methods), whereas Map entries are completely isolated from the prototype. Maps also accept any value as a key, including objects and symbols.
When set() fits best
Map.prototype.set() is the best fit when your keys are not limited to strings and you want insertion order plus predictable lookup behavior. It is a strong choice for caches, registries, lookup tables, and any data structure where keys may be objects or where key collisions would be hard to reason about with plain properties.
It also makes chained setup code easy to read. Because set() returns the Map, you can build a collection step by step without repeating the variable name over and over. That keeps initialization compact while still making each entry explicit.