JavaScript Map vs WeakMap — What is the Output?
This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Map Strong Reference Vs Weakmap and improve your technical interview readiness.
let obj = { data: "important" }
const map = new Map()
map.set(obj, "value")
obj = null
console.log(map.size)
Detailed Explanation
Why This Question Matters
Memory leaks are the silent killers of JavaScript applications. Most of us don't think about garbage collection (GC) until a browser tab starts eating 2GB of RAM or a Node.js process crashes in production.
The confusion usually stems from how JavaScript handles references. We're taught that if there are no more references to an object, it gets cleaned up. But when you put an object into a Map, you're creating a new reference. This is where the distinction between Map and WeakMap becomes critical. If you use the wrong one, you might be accidentally keeping thousands of objects alive in memory long after they should have been deleted.
Understanding the Code
Let's look at the snippet:
Here is exactly what's happening under the hood:
1. Object Creation: We create an object { data: "important" } and assign it to the variable obj. Now, obj holds a reference to that memory location.
2. The Map Entry: We call map.set(obj, "value"). A Map doesn't just store the value; it stores a strong reference to the key. Now there are two things pointing to our object: the variable obj and the internal entry inside the Map.
3. Nulling the Variable: We set obj = null. This removes the first reference. However, the Map still holds onto that object.
4. The Result: Because the Map still has a strong reference to the object, the garbage collector cannot reclaim that memory. The object stays alive, and the entry remains in the map.
When you call map.size, it will return 1.
Finding the Correct Answer
The correct answer is Option B (1).
If this had been a WeakMap, the result would be different. In a WeakMap, the keys must be objects, and the map holds a weak reference to them.
If we swapped Map for WeakMap in the code above:
- When obj = null happens, the only remaining reference to the object is the one inside the WeakMap.
- Since it's a "weak" reference, the garbage collector is allowed to ignore it and wipe the object from memory.
- Once the object is gone, the entry in the WeakMap automatically vanishes.
Crucial Note: You can't actually check the size of a WeakMap (it doesn't have a .size property) because the GC happens non-deterministically. If JS let you count the elements, the result would change randomly depending on when the garbage collector decided to run, which would be a nightmare for debugging.
Common Mistakes Developers Make
The biggest mistake is assuming that obj = null is enough to "delete" an object. It's not. It only deletes the *pointer* you're currently holding. If that object was passed into a cache, a global array, or a Map, it's still alive.
Another common trip-up is trying to use primitive values (like strings or numbers) as keys in a WeakMap. You can't. WeakMap only accepts objects. Why? Because primitives are not garbage collected in the same way; they are immutable and exist as constants or on the stack.
Lastly, developers often forget that WeakMap is not a drop-in replacement for Map. You lose the ability to iterate over the keys, you can't clear the map with .clear(), and you can't check the size. You trade convenience for memory safety.
Real-World Usage
When should you actually use a WeakMap in a production app?
1. Private Data/Metadata
Imagine you're writing a library and you want to attach some internal state to a DOM element without actually modifying the DOM element object (which would pollute the global namespace or clash with other libraries).
If the DOM element is removed from the page and deleted, the
WeakMap entry is automatically cleaned up. No manual cleanup required.
2. Caching (Memoization)
If you're caching the results of a heavy computation based on an object input, a WeakMap is your best friend. If the object used as the key is deleted elsewhere in your app, the cache entry dies with it. Using a standard Map here would create a massive memory leak as your cache grows indefinitely.
Key Takeaways
- Map holds strong references. If the map is alive, the keys are alive.
- WeakMap holds weak references. If the only reference to a key is the WeakMap, the GC will reclaim it.
- Use Map when you need to iterate over data or use primitive keys.
- Use WeakMap for metadata, caches, or any scenario where the lifecycle of the key should dictate the lifecycle of the value.
- Setting a variable to null doesn't guarantee memory release if a strong reference still exists elsewhere.
Why this matters
Understanding Map Strong Reference Vs Weakmap is crucial for passing technical interviews. In real-world applications, this concept often leads to subtle bugs if not handled correctly. For more details, you can always refer to the official MDN Documentation.