Keyed Collections: Map, Set, and Leak-Free WeakMap/WeakSet
Master modern ECMAScript collections. Compare Map vs Object, enforce uniqueness with Set, and eliminate memory leaks with garbage-collectable WeakMap/WeakSet.
By the end, you’ll be able to…
- Contrast Map with plain Objects regarding key types, iteration order, and performance.
- Leverage Set for O(1) uniqueness filtering and set algebra operations.
- Prevent memory leaks by associating private metadata with WeakMap and WeakSet.
01Map vs Plain Object: The Performance Reality
For years, plain JavaScript objects were used as hash maps. While convenient, plain objects have notable drawbacks: keys can only be strings or symbols (numbers are coerced to strings), objects come with inherited prototype keys (hasOwnProperty checks required), and determining size requires an expensive Object.keys(obj).length scan.
ES2015 introduced Map as a true keyed collection. In a Map, keys can be of ANY type—including objects, functions, and primitives. Maps remember the exact insertion order of keys, provide a clean O(1) .size property, and are heavily optimized by V8 for scenarios involving frequent additions and removals.
While plain JavaScript objects have historically been used as makeshift hash tables, they carry severe limitations: keys must be strings or symbols, they inherit unwanted prototype properties (like toString and constructor), and calculating their size requires calling Object.keys(obj).length in O(N) time.
The Map collection resolves all of these issues: it accepts keys of any type (including DOM nodes, functions, and object references), guarantees predictable insertion-order iteration, and provides an instant O(1) .size property.
02Set: High-Speed Uniqueness and Algebra
A Set is a collection of unique values where duplicate entries are automatically discarded. Checking whether an element exists in a Set (set.has(item)) is an O(1) constant-time hash lookup, compared to array.includes(item) which is an O(N) linear scan.
Modern ECMAScript introduces set algebra methods directly on Set: union(), intersection(), difference(), and isSubsetOf(), making collection comparisons blazingly fast and expressive.
03WeakMap and WeakSet: Eliminating Memory Leaks
In a standard Map, as long as the Map exists, any object used as a key is strongly held in memory. Even if your application drops all other references to that key object, the Map keeps it alive, preventing V8's garbage collector from sweeping it. This is a common source of memory leaks in caching layers.
WeakMap and WeakSet solve this permanently. A WeakMap holds WEAK references to its keys (which MUST be objects). If an object key has no other live references in the program, the engine automatically reclaims the object and silently deletes its entry from the WeakMap. Because keys can disappear at any time due to garbage collection, WeakMaps are not iterable and have no .size property.
04Why This Matters in Production
In production architectures, Maps and Sets drastically outperform arrays when performing frequent lookups, filtering uniqueness, and managing relational caches. In large applications, replacing array.includes() inside loops with a Set.has() lookup frequently reduces algorithm runtimes from O(N^2) (minutes) to O(N) (milliseconds).
Use WeakMap whenever you need to associate private state or metadata with objects whose lifecycle is controlled by an external system (such as DOM nodes, third-party libraries, or transient HTTP connection sockets).
The ideas worth keeping.
- Use Map over plain objects for dynamic keys, arbitrary key types, and frequent insertions/removals.
- Set provides O(1) lookups and instant deduplication of collections.
- WeakMap prevents memory leaks by allowing object keys to be garbage-collected when no longer referenced.
Make it yours.
Type and test your code right here in the interactive workspace. Run your solution, check the output, and compare with the worked guide when ready.
Exercise 1: Array Deduplication and Intersection
Write a function getCommonElements(arr1, arr2) that returns unique elements present in both arrays with O(N) efficiency.
Explore a worked solution
function getCommonElements(arr1, arr2) { const set1 = new Set(arr1); return [...new Set(arr2.filter(item => set1.has(item)))];}Converting arr1 to a Set allows O(1) lookup during filtering, keeping total time complexity strictly linear O(N).
Exercise 2: Private Instance Fields with WeakMap
Implement private property storage for a constructor function Person using a WeakMap closure so properties are leak-free and completely private.
Explore a worked solution
const privateData = new WeakMap();function Person(name) { privateData.set(this, { name });}Person.prototype.getName = function() { return privateData.get(this).name;};Using a WeakMap with this as the key keeps private state isolated and allows instances to be garbage collected cleanly.
What stayed with you?
Check the ideas while they’re fresh. Your answers stay in this page and feedback appears as you go.
Exercise 1: Array Deduplication and Intersection
Write a function getCommonElements(arr1, arr2) that returns unique elements present in both arrays with O(N) efficiency.
[Process exited with code 0 - No output]
Keep exploring.
The official references behind this lesson, when you want a second angle or the full details.
One lesson closer.
Reading is a start. Trying it yourself makes the connection.