![]() |
In JavaScript, we often work with data structures like Map
or Set
to associate keys with values or store collections of elements. However, when you need to associate data with objects without affecting the lifecycle of those objects, WeakMap
becomes a powerful and irreplaceable tool.
✅ What is a WeakMap
?
A WeakMap
is a collection of key/value pairs where:
- Keys must be objects (not primitives).
- Key references are weak, meaning they do not prevent garbage collection.
- It is not iterable: we cannot use
for...of
,.keys()
, or.entries()
to explore its contents.
These features make WeakMap
particularly useful in scenarios where you want to connect data to objects in a non-intrusive manner and without the risk of memory leaks.
๐ Why use WeakMap
?
- Memory management: Weak keys allow the automatic removal of unused objects.
- Transparent integration: Allows you to associate data with objects without modifying them.
- Security and encapsulation: The keys are not accessible from the outside; no one can enumerate them.
๐ WeakMap
vs Map
: Direct Comparison
Feature | Map |
WeakMap |
---|---|---|
Keys | Objects, primitives | Only objects |
Garbage collection | Keys kept in memory | Weakly referenced keys |
Iterability | Yes, with .keys() , .forEach() , etc. |
No |
Visibility | Accessible with .size , .entries() |
Inaccessible |
Typical use | Generic collections | Private data, temporary caches |
๐ Key points
-
Map
holds keys in memory, so it can cause memory leaks if not managed well. -
WeakMap
does not hold keys, so it is ideal for storing data associated with objects temporarily or privately. -
This behavior is crucial for:
-
automatic caching
-
dynamic resource management (e.g., DOM)
-
private data of objects that can be naturally destroyed
-
๐งน Concrete example: WeakMap
and Garbage Collection
๐ฏ Objective
Associate temporary data with DOM elements without causing memory leaks.
const elementData = new WeakMap();
function attachMetadata(element) {
const data = {
clickedAt: Date.now(),
temporarySetting: Math.random()
};
elementData.set(element, data);
}
function handleClick(event) {
const element = event.target;
attachMetadata(element);
console.log('Metadata stored:', elementData.get(element));
}
let button = document.createElement('button');
button.textContent = 'Click me';
document.body.appendChild(button);
button.addEventListener('click', handleClick);
setTimeout(() => {
document.body.removeChild(button);
button = null; // Remove last reference
// Now both the DOM element and its metadata can be garbage collected
}, 5000);
With a Map
, the element and its associated data would remain in memory.
With a WeakMap
, as soon as the element is no longer referenced, everything is automatically cleaned up by the garbage collector.
๐ Limitations of WeakMap
❌ 1. It is not iterable: you cannot access all keys or values
const wm = new WeakMap();
const obj = {};
wm.set(obj, 'data');
for (const [key, value] of wm) {
console.log(key, value); // ❌ TypeError: wm is not iterable
}
❌ 2. Keys must be objects: you can't use strings, numbers, etc.
const wm = new WeakMap();
wm.set('user', 'data'); // ❌ TypeError: Invalid value used as weak map key
❌ 3. No property .size
const wm = new WeakMap();
const a = {}, b = {};
wm.set(a, 1);
wm.set(b, 2);
console.log(wm.size); // ❌ undefined
❌ 4. No visibility on content
const wm = new WeakMap();
const obj = {};
wm.set(obj, 'secret');
console.log(wm.has(obj)); // ✔️ true
console.log([...wm.keys()]); // ❌ TypeError: wm.keys is not a function
๐งช Practical examples of using a WeakMap
๐ 1. Bind metadata to objects
user
object, but is stored in a separate, invisible structure outside of the defined functions.const metaData = new WeakMap();
function setMetadata(obj, data) {
metaData.set(obj, data);
}
function getMetadata(obj) {
return metaData.get(obj);
}
const user = { name: 'Alice' };
setMetadata(user, { role: 'admin' });
console.log(getMetadata(user)); // { role: 'admin' }
๐ 2. Private properties in a class
WeakMap
is used to keep the data count
out of direct reach of user code, emulating visibility private.const privateProps = new WeakMap();
class Counter {
constructor() {
privateProps.set(this, { count: 0 });
}
increment() {
const data = privateProps.get(this);
data.count++;
}
getCount() {
return privateProps.get(this).count;
}
}
const counter = new Counter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 2
console.log(counter.count); // undefined
๐ 3. Automatic Cache for Functions
WeakMap
, the cache associated with data
will be automatically removed when data
is no longer used, preventing unwanted memory accumulation.const cache = new WeakMap();
function process(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
const result = computeHeavyTask(obj);
cache.set(obj, result);
return result;
}
function computeHeavyTask(obj) {
return obj.value * 1000;
}
const data = { value: 5 };
console.log(process(data)); // 5000
console.log(process(data)); // 5000, cached
๐ฏ Conclusion
WeakMap
is a powerful tool for:
- Associate private data with objects without modifying them
- Manage caches automatically and securely
- Prevent memory leaks in dynamic scenarios (DOM, components)
It doesn't replace Map
, but it's essential in contexts where memory management and data privacy are crucial.
Follow me #techelopment
Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
whatsapp: Techelopment
youtube: @techelopment