What are the differences between `Map`/`Set` and `WeakMap`/`WeakSet` in JavaScript?
TL;DR
The primary difference between Map/Set and WeakMap/WeakSet in JavaScript lies in how they handle keys. Here's a breakdown:
Map vs. WeakMap
Maps allow any JavaScript value as a key and hold their keys and values strongly while the Map remains reachable. They are suitable for general-purpose key-value storage and are iterable in insertion order.
WeakMaps allow objects and non-registered symbols as keys. These keys are held weakly: an entry does not by itself keep its key reachable. WeakMaps are useful for associating metadata with a key without controlling that key's lifetime. Garbage collection timing is not observable or guaranteed.
- Caching data based on objects without preventing garbage collection of the objects themselves.
- Storing private data associated with DOM nodes without affecting their lifecycle.
Set vs. WeakSet
Similar to Map, Sets allow any data type as elements. The elements within a Set must be unique. Sets are useful for storing unique values and checking for membership efficiently. Common use cases include removing duplicates from arrays or keeping track of completed tasks.
WeakSet allows objects and non-registered symbols as elements. Like WeakMap keys, they are held weakly. WeakSets are useful when membership should not keep an object alive.
- Tracking DOM nodes that have been interacted with without affecting their memory management.
- Implementing custom object weak references for specific use cases.
Here's a table summarizing the key differences:
| Feature | Map | WeakMap | Set | WeakSet |
|---|---|---|---|---|
| Key Types | Any JavaScript value | Objects and non-registered symbols | Any JavaScript value (unique) | Objects and non-registered symbols (unique) |
| References | Strong keys and values | Weak keys; values are associated with the key's lifetime | Strong elements | Weak elements |
| Use Cases | General-purpose key-value storage | Caching, private DOM node data | Removing duplicates, membership checks | Object weak references, custom use cases |
Choosing between them
- Use
MapandSetfor most scenarios where you need to store key-value pairs or unique elements and want to maintain references to both the keys/elements and the values. - Use
WeakMapandWeakSetwhen membership should not keep an object or non-registered symbol alive. They are intentionally non-iterable, so useMaporSetif entries must be listed or counted.
Strong and weak reachability
Ordinary collections retain their entries strongly, while weak collections do not keep object keys or values alive by themselves.
That non-observable collection behavior is why WeakMap and WeakSet are not enumerable and accept only garbage-collectable values as weakly held entries.
Map/Set vs WeakMap/WeakSet
The key differences between Map/Set and WeakMap/WeakSet in JavaScript are:
- Key types:
MapandSetaccept any JavaScript value.WeakMapkeys andWeakSetelements must be objects or non-registered symbols; strings, numbers, registered symbols fromSymbol.for(), and most other primitives are rejected byset()/add(). - Memory management:
MapandSethold entries strongly.WeakMapkeys andWeakSetelements do not prevent otherwise unreachable keys from being reclaimed. AWeakMapvalue is not weak independently; it can be reclaimed when its key becomes unreachable. - Key enumeration: Keys in
MapandSetare enumerable (can be iterated over), while keys inWeakMapandWeakSetare not enumerable. This means you cannot get a list of keys or values from aWeakMaporWeakSet. sizeproperty:MapandSethave asizeproperty that returns the number of elements, whileWeakMapandWeakSetdo not have asizeproperty because their size can change due to garbage collection.- Use cases:
MapandSetare general-purpose collections.WeakMapandWeakSetare primarily for metadata, caching, and membership tied to another object's lifetime.
Map and Set are regular data structures that maintain strong references to their keys and values, while WeakMap and WeakSet are designed for scenarios where you want to associate data with objects without preventing those objects from being garbage collected when they are no longer needed.
Use cases of WeakMap and WeakSet
Tracking active users
In a chat application, you might want to track which user objects are currently active without preventing garbage collection when the user logs out or the session expires. We use a WeakSet to track active user objects. When a user logs out or their session expires, the user object can be garbage-collected if there are no other references to it.
const activeUsers = new WeakSet();// Function to mark a user as activefunction markUserActive(user) {activeUsers.add(user);}// Function to check if a user is activefunction isUserActive(user) {return activeUsers.has(user);}// Example usagelet user1 = { id: 1, name: 'Alice' };let user2 = { id: 2, name: 'Bob' };markUserActive(user1);markUserActive(user2);console.log(isUserActive(user1)); // trueconsole.log(isUserActive(user2)); // true// Simulate user logging outuser1 = null;// user1 is now eligible for garbage collectionconsole.log(isUserActive(user1)); // false
Detecting circular references
WeakSet provides a way of guarding against circular data structures by tracking which objects have already been processed.
// Create a WeakSet to track visited objectsconst visited = new WeakSet();// Function to traverse an object recursivelyfunction traverse(obj) {// Check if the object has already been visitedif (visited.has(obj)) {return;}// Add the object to the visited setvisited.add(obj);// Traverse the object's propertiesfor (let prop in obj) {if (Object.hasOwn(obj, prop)) {let value = obj[prop];if (typeof value === 'object' && value !== null) {traverse(value);}}}// Process the objectconsole.log(obj);}// Create an object with a circular referenceconst obj = {name: 'John',age: 30,friends: [{ name: 'Alice', age: 25 },{ name: 'Bob', age: 28 },],};// Create a circular referenceobj.self = obj;// Traverse the objecttraverse(obj);
Further reading
Map| MDNWeakMap| MDNSet| MDNWeakSet| MDNMapandSet| Javascript.infoWeakMapandWeakSet| Javascript.info