JavaScript WeakMap Data Structure
A WeakMap is a collection of key-value pairs similar to a Map, but with keys restricted to objects only. WeakMaps do not prevent their keys from being garbage collected.
Common use cases:
- Memory management: Automatically remove entries when keys are no longer referenced.
- Private data storage: Associate private data with objects without modifying them.
- Cache management: Store cached data tied to objects without memory leaks.
- DOM node metadata: Attach data to DOM elements safely.
Quick Links
What is a WeakMap?
A WeakMap is similar to a Map but with important differences:
- Keys must be objects (no primitive types allowed).
- Keys are held weakly, meaning if there are no other references to the key object, it can be garbage collected along with its value.
- WeakMaps are not iterable; you cannot loop over their contents.
- There is no clear() method, since entries are automatically removed when keys are collected.
This behavior helps prevent memory leaks by allowing unused keys and their data to be cleaned up automatically.
Creating a WeakMap
You can create a WeakMap in JavaScript using the new WeakMap() constructor. Unlike Map, a WeakMap only accepts objects as keys and does not prevent garbage collection of those keys.
1. Creating an Empty WeakMap
To create an empty WeakMap, use the constructor without arguments. Then add key-value pairs using the set() method.
// Creating an empty WeakMap
const cache = new WeakMap();
const obj1 = {};
const obj2 = {};
cache.set(obj1, 'cached data for obj1');
cache.set(obj2, 'cached data for obj2');
console.log(cache.get(obj1)); // Output: cached data for obj1
// Creating an empty WeakMap
const cache = new WeakMap();
const obj1 = {};
const obj2 = {};
cache.set(obj1, 'cached data for obj1');
cache.set(obj2, 'cached data for obj2');
console.log(cache.get(obj1)); // Output: cached data for obj1
2. Creating a WeakMap with Initial Values
You can initialize a WeakMap with an iterable of key-value pairs, where keys must be objects.
const objA = {id: 1};
const objB = {id: 2};
const weakMap = new WeakMap([
[objA, 'data for objA'],
[objB, 'data for objB']
]);
console.log(weakMap.get(objB)); // Output: data for objB
const objA = {id: 1};
const objB = {id: 2};
const weakMap = new WeakMap([
[objA, 'data for objA'],
[objB, 'data for objB']
]);
console.log(weakMap.get(objB)); // Output: data for objB
Remember, WeakMap keys must be objects. Primitive values like strings or numbers are not allowed.
Accessing WeakMap Elements
Once you have created a WeakMap, you can access, check for existence, and delete its elements using the following methods:
1. Retrieving a Value with get()
Use the get(key) method to retrieve the value associated with the specified key object. If the key does not exist, it returns undefined.
const wm = new WeakMap();
const obj = {};
wm.set(obj, 'value associated with obj');
console.log(wm.get(obj)); // Output: value associated with obj
console.log(wm.get({})); // Output: undefined (different object key)
const wm = new WeakMap();
const obj = {};
wm.set(obj, 'value associated with obj');
console.log(wm.get(obj)); // Output: value associated with obj
console.log(wm.get({})); // Output: undefined (different object key)
2. Checking if a Key Exists with has()
The has(key) method returns true if the specified key exists in the WeakMap, otherwise false.
const wm = new WeakMap();
const obj = {};
wm.set(obj, 123);
console.log(wm.has(obj)); // Output: true
console.log(wm.has({})); // Output: false (different object)
const wm = new WeakMap();
const obj = {};
wm.set(obj, 123);
console.log(wm.has(obj)); // Output: true
console.log(wm.has({})); // Output: false (different object)
3. Removing a Key-Value Pair with delete()
Use the delete(key) method to remove the key and its associated value from the WeakMap. It returns true if the element existed and was removed, otherwise false.
const wm = new WeakMap();
const obj = {};
wm.set(obj, 'some data');
console.log(wm.delete(obj)); // Output: true
console.log(wm.has(obj)); // Output: false
const wm = new WeakMap();
const obj = {};
wm.set(obj, 'some data');
console.log(wm.delete(obj)); // Output: true
console.log(wm.has(obj)); // Output: false
Note that WeakMap does not provide methods to iterate over its elements or get its size due to its weakly held keys.
Modifying WeakMap Elements
Since WeakMap stores key-value pairs where keys must be objects, modifying elements involves updating the value associated with an existing key object.
1. Updating the Value for an Existing Key
To update a value, call set(key, newValue) with the existing key object. This overwrites the old value with the new one.
const wm = new WeakMap();
const obj = { id: 1 };
wm.set(obj, 'initial value');
console.log(wm.get(obj)); // Output: initial value
wm.set(obj, 'updated value');
console.log(wm.get(obj)); // Output: updated value
const wm = new WeakMap();
const obj = { id: 1 };
wm.set(obj, 'initial value');
console.log(wm.get(obj)); // Output: initial value
wm.set(obj, 'updated value');
console.log(wm.get(obj)); // Output: updated value
2. Adding New Key-Value Pairs
If the key does not already exist in the WeakMap, calling set() will add a new key-value pair.
const newObj = { id: 2 };
wm.set(newObj, 'new entry');
console.log(wm.get(newObj)); // Output: new entry
const newObj = { id: 2 };
wm.set(newObj, 'new entry');
console.log(wm.get(newObj)); // Output: new entry
3. Important Notes
- Keys must be objects. Primitive values like strings or numbers cannot be used as keys.
- There is no direct way to modify a key, but since keys are objects, you can mutate the object itself outside the WeakMap.
- Updating values does not affect garbage collection behavior of keys.
WeakMap Methods
WeakMap provides a limited set of methods to interact with the map. Here are the main ones:
- set(key, value): Adds or updates the value associated with the given object key.
- get(key): Returns the value associated with the key, or undefined if none exists.
- has(key): Returns true if the key exists in the WeakMap, otherwise false.
- delete(key): Removes the specified key and its associated value from the WeakMap. Returns true if the key was found and deleted, otherwise false.
Example Usage
const wm = new WeakMap();
const obj1 = {};
const obj2 = {};
wm.set(obj1, 'value for obj1');
wm.set(obj2, 'value for obj2');
console.log(wm.get(obj1)); // Output: value for obj1
console.log(wm.has(obj2)); // Output: true
wm.delete(obj1);
console.log(wm.has(obj1)); // Output: false
console.log(wm.get(obj1)); // Output: undefined
const wm = new WeakMap();
const obj1 = {};
const obj2 = {};
wm.set(obj1, 'value for obj1');
wm.set(obj2, 'value for obj2');
console.log(wm.get(obj1)); // Output: value for obj1
console.log(wm.has(obj2)); // Output: true
wm.delete(obj1);
console.log(wm.has(obj1)); // Output: false
console.log(wm.get(obj1)); // Output: undefined
WeakMap vs Map: Key Differences
- Key Types: WeakMap keys must be objects; Map keys can be any value.
- Garbage Collection: WeakMap keys are held weakly, allowing garbage collection if no other references exist; Map keys are held strongly.
- Iteration: Map is iterable; WeakMap is not iterable (no methods like keys() or entries()).
- Methods: WeakMap lacks methods like clear() or size property.
- Use Case: WeakMap is ideal for storing metadata associated with objects without preventing their garbage collection.
Frequently Asked Questions
What is a WeakMap in JavaScript?
What is a WeakMap in JavaScript?
A WeakMap is a special key-value collection where keys must be objects, and the values can be any type. It supports automatic garbage collection for keys, making it memory-efficient.
When should I use a WeakMap?
When should I use a WeakMap?
Use a WeakMap when storing private or temporary data associated with an object — especially when that data should not prevent the object from being garbage-collected.
How do you create a WeakMap?
How do you create a WeakMap?
Use new WeakMap() to create one. You can also initialize it with pairs: const wm = new WeakMap([[obj1, value1]]).
What methods are available on a WeakMap?
What methods are available on a WeakMap?
A WeakMap supports set(), get(), has(), and delete(). It does not provide size or iteration methods.
Can I iterate over a WeakMap?
Can I iterate over a WeakMap?
No, you cannot iterate over a WeakMap. It is not enumerable, and you can't retrieve keys or values due to the weak reference behavior.
What's Next?
Up next: JavaScript WeakSets – a collection designed to store objects weakly, helping with memory efficiency and temporary object tracking.