Now that you understand the standard Map data structure, it is time to look at its close sibling: the WeakMap.
A WeakMap is a specialized collection of key-value pairs that behaves similarly to a standard Map, but with a few critical, performance-saving differences regarding memory management and garbage collection.
If you attempt to use a WeakMap exactly like a standard Map, you will quickly run into errors. Here are the two absolute rules of WeakMap:
In a standard Map, you can use primitive types (strings, numbers, booleans) as keys. In a WeakMap, keys can ONLY be objects. You cannot use a string or a number as a key.
A WeakMap does not have a size property, and you cannot iterate over it. Methods like keys(), values(), entries(), and forEach() do not exist on a WeakMap. You cannot check how many items are inside it or loop through its contents.
You might be wondering: "If WeakMaps only take object keys and I can't even loop through them, why do they exist?"
The answer lies in the name: Weak.
In JavaScript, if you store an object in a regular variable or a standard Map, the system’s Garbage Collector (the engine that deletes unused data to free up memory) will never delete that object as long as the Map exists. The Map holds a "strong" reference to it.
A WeakMap holds a "weak" reference to its keys.
If the object used as a key in a WeakMap is deleted everywhere else in your program, the Garbage Collector will realize it is no longer needed and will automatically delete the key and its value from the WeakMap as well!
let weakMap = new WeakMap();// We create an object let user = { name: "Akash" };
// We assign some secret data to the user object using WeakMap weakMap.set(user, "Secret admin privileges");
console.log(weakMap.has(user)); // true
// Later in the program, the user object is deleted/overwritten! user = null;
// Because
useris null everywhere else, the WeakMap automatically // drops the key and the "Secret admin privileges" value from memory!
This automatic cleanup makes WeakMap an incredibly efficient tool for preventing memory leaks in large applications.
Because they are not iterable, WeakMap objects only have four basic methods to interact with specific, known keys:
set(key, value): Adds a new key-value pair to the WeakMap.get(key): Retrieves the value associated with the object key.has(key): Returns a boolean indicating if the object key exists.delete(key): Removes the key-value pair.
const weak = new WeakMap();
const objKey1 = {};
const objKey2 = window; // Using the global window object
// Setting values
weak.set(objKey1, "Data for object 1");
weak.set(objKey2, "Data for object 2");
// Getting values
console.log(weak.get(objKey1)); // "Data for object 1"
// Checking existence
console.log(weak.has(objKey2)); // true
// Deleting
weak.delete(objKey1);
console.log(weak.has(objKey1)); // false
While beginners might not use WeakMap often, expert developers use it to solve two common architectural problems:
Imagine you want to keep track of how many times a user clicked a specific HTML button on your page. If you use a regular Map to map the button object to a click-count, and the button is later removed from the screen, the Map will keep the button's data in memory forever (a memory leak).
If you use a WeakMap, the moment the button is removed from the DOM and has no other references, its click-count data is gracefully erased from memory.
In Object-Oriented Programming (OOP), developers use WeakMap to store private data that belongs to an object. By using this (the object instance) as the key in a WeakMap, the private data is securely hidden from the outside world, but easily accessible to the object's methods. When the object instance is deleted, its private data is automatically deleted with it.
What is a fundamental rule regarding the keys you can use in a JavaScript WeakMap?