JavaScript WeakMap and WeakSet

WeakMap and WeakSet are special versions of Map and Set that hold weak references to objects. A weak reference means: if no other part of the program holds on to an object, JavaScript is free to delete it from memory — even if the object is still in a WeakMap or WeakSet. This prevents memory leaks in long-running applications.

Why "Weak"?

In a regular Map, keys are held strongly — the object stays in memory as long as the Map exists. In a WeakMap, keys are held weakly — when the object is no longer referenced anywhere else, the garbage collector removes it automatically, and the WeakMap entry disappears with it.

Diagram: Strong vs Weak Reference

Regular Map:
  user object ◄─── Map (strong ref) ◄─── code
  As long as Map exists → user object stays in memory

WeakMap:
  user object ◄─── WeakMap (weak ref)
  user object ◄─── code (strong ref)

  When code stops referencing user:
  → garbage collector removes user object
  → WeakMap entry disappears too (automatically)

WeakMap

A WeakMap is a key-value store where keys must be objects (not primitives). Values can be anything.

Creating and Using WeakMap

let weakMap = new WeakMap();

let user1 = { name: "Ravi" };
let user2 = { name: "Priya" };

weakMap.set(user1, { role: "admin" });
weakMap.set(user2, { role: "editor" });

console.log(weakMap.get(user1)); // { role: "admin" }
console.log(weakMap.has(user2)); // true

weakMap.delete(user2);
console.log(weakMap.has(user2)); // false

WeakMap Methods

MethodWhat it Does
set(key, value)Stores a value for the given object key
get(key)Retrieves the value for the key
has(key)Returns true if the key exists
delete(key)Removes the entry

WeakMap has NO size, NO keys(), NO forEach(). You cannot iterate over it. This is intentional — you should not need to loop over weakly held data.

WeakMap: Automatic Cleanup

let weakMap = new WeakMap();

let session = { userId: 42 };
weakMap.set(session, { token: "abc123" });

// Later, session is no longer needed
session = null; // the original object has no more strong references

// Garbage collector eventually removes the object
// The weakMap entry disappears on its own — no memory leak

Diagram: WeakMap Cleanup

Before:
  session variable ──► { userId: 42 }
  weakMap           ──► { userId: 42 } → { token: "abc123" }

After session = null:
  session variable ──► null
  { userId: 42 } has NO strong references left
  Garbage collector removes it
  weakMap entry is gone too

Real Use Case: Attaching Private Data to Objects

WeakMap lets you associate private metadata with an object without modifying the object itself.

const privateData = new WeakMap();

class BankAccount {
  constructor(owner, balance) {
    privateData.set(this, { balance });
    this.owner = owner;
  }

  deposit(amount) {
    let data = privateData.get(this);
    data.balance += amount;
  }

  getBalance() {
    return privateData.get(this).balance;
  }
}

let acc = new BankAccount("Anjali", 1000);
acc.deposit(500);
console.log(acc.getBalance()); // 1500
console.log(acc.balance);      // undefined — truly private

WeakSet

A WeakSet is like a Set — but it only stores objects (not primitives), and it holds them weakly. When an object has no other strong references, it is removed from the WeakSet automatically.

Creating and Using WeakSet

let weakSet = new WeakSet();

let task1 = { id: 1, name: "Login" };
let task2 = { id: 2, name: "Signup" };

weakSet.add(task1);
weakSet.add(task2);

console.log(weakSet.has(task1)); // true
weakSet.delete(task1);
console.log(weakSet.has(task1)); // false

WeakSet Methods

MethodWhat it Does
add(object)Adds the object
has(object)Checks if the object exists
delete(object)Removes the object

Like WeakMap, WeakSet has no size and is not iterable.

Real Use Case: Tracking Visited Objects

WeakSet is ideal for marking objects that have been processed without modifying the object or leaking memory.

let processed = new WeakSet();

function processUser(user) {
  if (processed.has(user)) {
    console.log("Already processed:", user.name);
    return;
  }

  // Do work here
  console.log("Processing:", user.name);
  processed.add(user);
}

let u = { name: "Kiran" };
processUser(u); // Processing: Kiran
processUser(u); // Already processed: Kiran

// When u is set to null, the WeakSet entry cleans itself up

Diagram: WeakSet Tracking

processUser(u) called first time:
  processed.has(u) → false
  → do work, add to WeakSet
  processed = WeakSet{ u }

processUser(u) called second time:
  processed.has(u) → true
  → skip, print "Already processed"

WeakMap vs Map, WeakSet vs Set

FeatureMap / SetWeakMap / WeakSet
Key / Value typeAny typeKeys/members must be objects
IterabilityYes (forEach, for...of)No
size propertyYesNo
Memory managementManual (holds objects)Automatic (garbage collected)
Best forGeneral key-value or setsPrivate data, tracking, caching

When to Use WeakMap or WeakSet

  • Attaching metadata or private data to objects without modifying them.
  • Tracking which DOM elements have been set up, without keeping them in memory after removal.
  • Caching results tied to objects that may be discarded.
  • Any situation where you want automatic memory cleanup when objects go out of use.

Summary

WeakMap and WeakSet store object references weakly — when no other code references the object, it gets garbage collected and the weak collection entry disappears automatically. WeakMap stores key-value pairs keyed on objects. WeakSet stores unique objects. Neither supports iteration or size checking. They are the right tool when you need to associate data with objects without causing memory leaks — especially in long-running apps where objects are created and destroyed frequently.

Leave a Comment

Your email address will not be published. Required fields are marked *