Back to KB
Difficulty
Intermediate
Read Time
7 min

JavaScript Map, Set, WeakMap, and WeakSet: When to Use Which

By Codcompass Team··7 min read

Beyond Plain Objects: Mastering JavaScript’s Native Collection Primitives

Current Situation Analysis

Modern JavaScript applications routinely manage dynamic state, cache API responses, track DOM lifecycles, and deduplicate user inputs. Despite this, a significant portion of codebases still default to plain objects ({}) and arrays ([]) for every storage need. This habit stems from historical JavaScript patterns where objects served as the universal dictionary. However, treating objects as general-purpose maps introduces hidden performance costs and memory management overhead.

The core problem is misunderstood. Developers often assume that because objects support key-value storage, they are interchangeable with Map and Set. They are not. Plain objects carry prototype chain lookups, coerce non-string keys to [object Object], lack native size tracking, and require manual iteration setup. More critically, they hold strong references indefinitely, forcing developers to write explicit cleanup logic in long-running applications like SPAs or Node.js servers.

Engine-level data confirms the divergence. V8 optimizes objects for stable, predictable shapes (hidden classes). When keys are added or removed dynamically, the engine deoptimizes, falling back to dictionary mode with slower lookups. Map and Set bypass this entirely, maintaining O(1) average complexity for insertions, deletions, and lookups regardless of key volatility. Meanwhile, WeakMap and WeakSet integrate directly with the garbage collector, automatically releasing memory when key objects lose all external references. Ignoring these primitives means trading engine optimizations for manual bookkeeping, increasing bundle size and runtime latency.

WOW Moment: Key Findings

Selecting the correct collection primitive fundamentally changes how your application handles memory, iteration, and lookup performance. The following comparison isolates the operational characteristics that dictate architectural decisions.

ApproachKey ConstraintsMemory BehaviorIteration SupportOptimal Workload
Plain ObjectString/Symbol onlyStrong referencesManual (Object.keys)Static configuration, JSON serialization
MapAny typeStrong referencesNative (for...of, .entries)Dynamic key-value pairs, frequent mutations
SetAny typeStrong referencesNative (for...of, .values)Deduplication, membership testing
WeakMapObject onlyWeak references (GC-safe)NonePrivate state, DOM metadata, object caching
WeakSetObject onlyWeak references (GC-safe)NoneObject lifecycle tracking, type branding

This breakdown reveals a critical insight: iteration capability and memory lifecycle are inversely correlated. Strong-reference collections (Map, Set) support iteration and size tracking but require manual cleanup. Weak-reference collections (WeakMap, WeakSet) eliminate cleanup overhead but sacrifice iteration and .size. Understanding this trade-off prevents architectural mismatches, such as attempting to serialize a WeakMap or expecting deterministic ordering from a garbage-collected structure.

Core Solution

Building a pro

🎉 Mid-Year Sale — Unlock Full Article

Base plan from just $4.99/mo or $49/yr

Sign in to read the full article and unlock all 635+ tutorials.

Sign In / Register — Start Free Trial

7-day free trial · Cancel anytime · 30-day money-back