Skip to main content

Menu

System onlineAI Tutorials / 2026

AI Tutorials
Knowledge search

Recent · Popular · Tutorials

  • dart3 tutorials
  • java1 tutorial
  • Javascript3 tutorials
  • Node.js Introduction2 tutorials
  • dartdart · General · In depth
  • JavascriptJavascript · Advanced · In depth
  • JavascriptJavascript · Advanced · Mid
  • JavascriptJavascript · Advanced · Short

Find a tutorial

Tell the assistant what you want to learn. It suggests published chapters.

For example: “I want to learn Rust ownership from the start.” The conversation is kept only in this tab.

0 / 2,000 characters

Enter to send, Shift+Enter for a new line. Do not include personal information.

Chapter 13

Map, Set, and Built-in Collections

This chapter covers the built-in keyed and grouped collections: `Map`, `Set`, `WeakMap`, `WeakSet`, and how they differ from plain objects and arrays. It assumes you are comfortable with objects, property lookup, the prototype chain, iteration protocols, reference semantics, and garbage collection b
Level: AdvancedLength: In depth3 min read

Read at another depth

Map, Set, and Built-in Collections

This chapter covers the built-in keyed and grouped collections: Map, Set, WeakMap, WeakSet, and how they differ from plain objects and arrays. It assumes you are comfortable with objects, property lookup, the prototype chain, iteration protocols, reference semantics, and garbage collection basics.

Why Map instead of an object

A plain object is a hash-like structure, but it inherits Object.prototype and coerces every key to a string (or symbol). Map is a true dictionary: keys can be any value, including objects, functions, NaN, and undefined, and insertion order is guaranteed for all keys.

Code example in javascript
const byId = new Map();
const key = { id: 1 };
byId.set(key, 'data for this object');
console.log(byId.get(key));        // 'data for this object'
console.log(byId.get({ id: 1 }));  // undefined — identity, not structural, equality
console.log(byId.size);            // 1

Key differences from objects:

ConcernObjectMap
Key typesstrings and symbols onlyany value, compared by SameValueZero
Prototype pollution`__proto__`, `toString` collisions possiblenone; keys are stored in an internal slot
Sizemanual (`Object.keys().length`)`.size`
Iteration ordermostly insertion order, but integer-like keys come firststrict insertion order
Direct iterationnot iterableiterable; `[...map]` yields `[key, value]` pairs
Serialization`JSON.stringify` worksnot natively serializable
Performance on frequent adds/deletesoften slower for large, mutating mapstuned for insert/delete workloads

The SameValueZero algorithm differs from === only in treating NaN as equal to itself, which is why a Map can use NaN as a working key.

When an object is still the right choice

Prefer an object when: keys are a fixed schema, the data crosses JSON.stringify, or you rely on property access syntax and destructuring. Prefer Map when keys are dynamic, non-string, or the collection mutates heavily.

Set

Set is a collection of unique values under the same key semantics as Map — in fact, internally a Set is modeled as a Map where each entry has undefined as its value.

Code example in javascript
const tags = new Set(['js', 'async', 'js']);
console.log(tags.size);          // 2
console.log(tags.has('async'));  // true
tags.delete('js');
for (const t of tags) console.log(t); // 'async'

// Deduplicating values from an array
const unique = [...new Set([1, 2, 2, 3])]; // [1, 2, 3]

Sets support the usual algebra operations, which you compose yourself since there is no union method:

Code example in javascript
const a = new Set([1, 2, 3]);
const b = new Set([3, 4]);
const union = new Set([...a, ...b]);                 // {1,2,3,4}
const inter = new Set([...a].filter(x => b.has(x))); // {3}
const diff  = new Set([...a].filter(x => !b.has(x)));// {1,2}

has on a Set and get on a Map are approximately O(1) — implementations use hash tables keyed by value identity — versus O(n) for includes on arrays. Replacing array-membership checks with a Set in a hot loop is a common, effective optimization.

WeakMap and WeakSet

WeakMap and WeakSet hold their keys weakly: a key that is only referenced by the collection does not prevent garbage collection, and the entry vanishes when the key is collected. This is the tool for attaching metadata to objects you do not own, without leaking memory.

Code example in javascript
const metadata = new WeakMap();
let node = { name: 'dom-node' };
metadata.set(node, { visits: 3 });
node = null; // the entry becomes collectible; metadata will not leak it

The constraints follow from the implementation: keys must be objects (or non-registered symbols), the collections are not iterable, and there is no .size, because the runtime does not expose when collection happens. You cannot enumerate a WeakMap — enumeration would have to keep weak entries alive to show them.

Typical uses: private per-instance state, caches keyed by object, and associating data with DOM nodes or library objects.

Internals and gotchas

  • Map and Set iteration is insertion-ordered, but deleting and re-adding a key moves it to the end of the iteration order.
  • Identity, not structure, governs keys: two equal-looking objects are different keys. Use a serialized string key or a composite key type if you need structural keying.
  • Mutating an object does not change its hash — identity is the key — so mutable keys are safe, unlike in some languages.
  • Map/Set/WeakMap cannot be cloned by structuredClone's handling of WeakMaps (weak entries are dropped) and require manual reconstruction for JSON.
  • Per spec, Map operations have no specified complexity bound, but in practice all mainstream engines are hash-table backed; do not assume sorted order.

Decision criteria

  1. Fixed schema, JSON boundary → plain object.
  2. Dynamic or non-string keys, heavy mutation → Map.
  3. Uniqueness or fast membership → Set.
  4. Metadata attached to objects you don't own, or a cache that must not retain → WeakMap/WeakSet.

Exercise

You need to count how many times each word appears, then serialize the result to JSON. Map or object, and why?

Show answer

Either works, but an object (or a Map converted at the boundary) is the pragmatic choice if the immediate next step is JSON serialization, which Map does not support natively. Use a Map during processing for O(1) updates and clean key semantics, then Object.fromEntries(map) before serializing.

Exercise

Why can't WeakMap keys be primitives like strings?

Show answer

Primitives are values, not references, so there is nothing to hold weakly — a primitive key would either keep the entry alive forever or require an arbitrary rule for "collecting" a value. Requiring object keys gives the GC a clear reference to observe.

Spotted a mistake, or code that does not work?

Report an issue

Chapter: Map, Set, and Built-in Collections

0 / 2,000 characters

Plain text, for example: the second code sample does not compile. Do not include personal information.

You can't do that