JavaScript Map, Set, WeakMap, and WeakSet
Choose keyed collections by behavior: Map key/value association, Set membership and set algebra, and weak collections for non-enumerable object or symbol associations.
Intermediate
Map, Set, WeakMap, and WeakSet solve a different problem from arrays and plain objects: keyed collection. This lesson teaches how keys are compared, how insertion order affects iteration, why object identity matters, when Set algebra is useful, and why weak collections deliberately give up enumeration. The goal is to choose a collection by behavior rather than by memorizing method names.
Map: keys are values, not property names
A Map stores key/value pairs, and its keys may be arbitrary ECMAScript values. A key is identified using SameValueZero semantics, so NaN can be a key and -0 and +0 are treated as the same key. Unlike object property keys, a Map does not coerce an object key into a string.
Output
Ready to run.
Output
Ready to run.
Quick check
Which Map key comparison behavior is demonstrated here?
const answer = ;
Quick check
Which value can be a Map key without being converted to a string?
const answer = ;
set(), get(), has(), delete(), and size
set returns the Map, so calls can be chained. Setting an existing key replaces its value without creating a second entry. has asks whether a key is present; get retrieves its value; delete reports whether an entry was removed; size reports the number of live entries.
Output
Ready to run.
Quick check
What happens when set() is called with a key that is already present?
const answer = ;
Object identity matters for object keys
Two separately created objects are different Map keys even if they contain identical properties. Reusing the same object reference retrieves the associated value. This makes Map useful for associating metadata with specific object identities.
Output
Ready to run.
Quick check
Why does metadata.get(second) return undefined in this example?
const answer = ;
Map construction and insertion order
A Map constructor accepts an iterable of key/value pairs. Map iteration follows the collection order of its entries: keys(), values(), entries(), and the default iterator expose that order. Updating an existing key does not move it to the end.
Output
Ready to run.
Quick check
After updating an existing Map key, where does that entry appear during iteration?
const answer = ;
Set: uniqueness is the behavior
A Set stores values without duplicates. Like Map keys, Set membership uses SameValueZero-style semantics, so NaN can be present and repeated additions do not create additional entries. Set preserves insertion order for iteration.
Output
Ready to run.
Quick check
What does adding the same value to a Set again do?
const answer = ;
Set algebra: combine, compare, and subtract
Modern Set methods let you express common set relationships directly. union combines values, intersection keeps shared values, difference removes values found in another collection, and symmetricDifference keeps values present in exactly one side. isSubsetOf, isSupersetOf, and isDisjointFrom answer relationship questions without manual loops.
Output
Ready to run.
Quick check
Which method keeps only values present in both sets?
const answer = ;
Map versus Set: choose by the data relationship
Use Map when each key identifies an associated value. Use Set when the value itself is the membership you care about. Arrays remain the better fit when position and duplicate values are meaningful. Plain objects remain useful when string or symbol property keys and ordinary object behavior are what you need.
Output
Ready to run.
Quick check
Which collection directly models “has this identifier been seen?”
const answer = ;
WeakMap: private association without enumeration
WeakMap associates values with keys that can be held weakly: objects and symbols. It intentionally provides no way to enumerate its keys or values. The key must be supplied to observe an entry. This makes it useful for metadata tied to an object identity without creating a collection that can enumerate those keys.
Output
Ready to run.
Quick check
Why can you not write [...weakMap.keys()]?
const answer = ;
WeakSet: weak membership tracking
WeakSet is the membership-only counterpart to WeakMap. It stores objects and symbols as weakly held values, supports add/has/delete, and does not expose enumeration. It is appropriate when the question is “has this particular object been seen or marked?” rather than “which objects are present?”
Output
Ready to run.
Quick check
Which question is WeakSet designed to answer?
const answer = ;
Weak collections and garbage collection
Weak does not mean “automatically empty right now.” The specification permits collection of entries when their weakly held keys or values are no longer live, but the timing is not observable through WeakMap or WeakSet enumeration because enumeration does not exist. Do not build program logic that waits for garbage collection.
Output
Ready to run.
Quick check
Which statement about garbage collection and WeakMap is correct?
const answer = ;
The iterator boundary: keyed collections are iterable when the API says so
Map and Set expose iterators because their contents are meant to be observable. WeakMap and WeakSet do not. This difference is an important bridge to the next curriculum unit on iterators: being a collection does not automatically mean being enumerable.
Output
Ready to run.
Quick check
Which pair is intentionally not iterable?
const answer = ;
Map: getOrInsert keeps an existing value
Map.prototype.getOrInsert(key, value) returns the existing value when the key is already present. Only when the key is absent does it insert the supplied value and return that value. Unlike a manual has() check, the operation expresses the lookup-or-default intent directly. This lesson does not re-teach Map key equality or ordinary set()/get() behavior; those remain the primary concepts above.
Output
Ready to run.
Quick check
If the Map already contains the key "theme", what does getOrInsert("theme", "light") return?
const answer = ;
Map: getOrInsertComputed calculates only when needed
Map.prototype.getOrInsertComputed(key, callback) is the lazy form. If the key exists, the callback is not called. If the key is absent, the callback is called with the canonicalized key and its returned value is inserted and returned. The callback therefore belongs to the missing-value path, not the normal lookup path.
Output
Ready to run.
Quick check
When the key is already present, what should getOrInsertComputed do with its callback?
const answer = ;
WeakMap: getOrInsert preserves weak-key semantics
WeakMap.prototype.getOrInsert(key, value) has the same lookup-or-default shape, but the key must still be a value that the WeakMap can hold weakly. The new method does not make WeakMap enumerable and does not change its weak-liveness semantics. Those properties remain the reason to choose WeakMap in the first place.
Output
Ready to run.
Quick check
What remains true when WeakMap gains getOrInsert?
const answer = ;
WeakMap: computed insertion is lazy too
WeakMap.prototype.getOrInsertComputed(key, callback) combines weak-key association with lazy value construction. Existing keys return their stored value without invoking the callback; missing keys invoke the callback with the key, then store and return the result. The method does not expose enumeration or make garbage-collection timing observable.
Output
Ready to run.
Quick check
For a present WeakMap key, what is the observable callback count after two getOrInsertComputed calls?
const answer = ;
Authoring rules
Choose Map when you need arbitrary keys mapped to values; choose Set when membership is the data; choose WeakMap or WeakSet when association or membership should be tied to weakly held object or symbol identity and enumeration is not required. Remember that object keys use identity, Map and Set preserve insertion order for their observable iteration, and weak collections must never be treated as garbage-collection notifications.
Practice: redesign the data relationship
Take a list of user records. First build a Map from stable user IDs to records. Then build a Set of IDs that have completed a task. Finally, identify which records are both known users and completed users without mutating the original records. For an object-keyed cache, replace the ID Map with a WeakMap only if object identity is the actual key and you do not need enumeration.
Specification references
Normative source: ECMA-262, Keyed Collections. The living specification defines Map and Set key semantics, insertion-order iteration, modern Set relationship operations, and the intentionally non-enumerable behavior of WeakMap and WeakSet. The curriculum uses those rules as the technical source while presenting observable examples first.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.