What's the difference between Map and WeakMap?

👨‍💻 Frontend Developer 🟠 May come up 🎚️ Medium
#JavaScript #Collections #JS Basics

Brief Answer

Map and WeakMap are both key-value collections, but they have important differences:

  1. Map can use any values as keys, while WeakMap only uses objects as keys 🗝️
  2. Map can be iterated, but WeakMap cannot 🔍
  3. WeakMap automatically removes pairs when the key object is no longer used anywhere else 🗑️
// Map — any keys
const map = new Map([[1, 'number'], ['a', 'string'], [{}, 'object']]);
 
// WeakMap — only objects as keys
const obj = {};
const weakMap = new WeakMap([[obj, 'value']]);

Full Answer

Think of Map as a regular box with compartments, where each compartment has a label with any name. And WeakMap is a magical box that throws away compartments when no one remembers their labels anymore! 📦✨

Main Differences

Key Types

// Map can use any keys
const map = new Map();
map.set(1, 'number');    // number ✅
map.set('a', 'string');  // string ✅
map.set({}, 'object');   // object ✅
 
// WeakMap only objects as keys
const weakMap = new WeakMap();
const keyObj = {};
// weakMap.set('string', 'value'); // ❌ Error!
weakMap.set(keyObj, 'value');      // ✅ Only objects

Iterating Elements

const map = new Map([['a', 1], ['b', 2]]);
 
// Map can be iterated
for (const [key, value] of map) {
  console.log(key, value); // 'a' 1, 'b' 2
}
 
const weakMap = new WeakMap([[{}, 'value']]);
 
// ❌ WeakMap cannot be iterated!
// for (const [key, value] of weakMap) // Error!

How WeakMap Works

WeakMap is like a secret safe that destroys documents when their owner forgets about them. If no one holds a reference to the key object anymore, WeakMap forgets the key-value pair automatically! 🔐

Automatic Cleanup

let obj = { id: 1 };
const weakMap = new WeakMap([[obj, 'private data']]);
 
// When obj is no longer used by anyone
obj = null;
 
// Pair will be automatically removed from WeakMap
// Garbage collector takes care of it 🗑️

When to Use Map

For Storing Any Key-Value Pairs

// Caching results
const cache = new Map();
 
function getData(key) {
  if (cache.has(key)) {
    return cache.get(key);
  }
  
  const result = fetchData(key);
  cache.set(key, result);
  return result;
}

When Iteration is Needed

// Need to go through all pairs
const config = new Map([['theme', 'dark'], ['lang', 'en']]);
 
config.forEach((value, key) => {
  console.log(`${key}: ${value}`);
});

When to Use WeakMap

For Private Data

// Private user data
const privateData = new WeakMap();
 
class User {
  constructor(name) {
    this.name = name;
    // Private data not visible from outside
    privateData.set(this, { password: 'secret' });
  }
  
  getPassword() {
    return privateData.get(this).password;
  }
}

For Caching with Automatic Cleanup

// Cache that cleans itself
const cache = new WeakMap();
 
function process(obj) {
  if (cache.has(obj)) {
    return cache.get(obj); // from cache
  }
  
  const result = heavyCalculation(obj);
  cache.set(obj, result); // to cache
  return result;
}
 
// When obj object is no longer needed,
// cache will automatically clear

Common Mistakes

Trying to Use Primitives as Keys in WeakMap

// ❌ Error!
const weakMap = new WeakMap();
// weakMap.set('key', 'value'); // TypeError!
// weakMap.set(123, 'value');   // TypeError!
 
// ✅ Correct
const obj = {};
weakMap.set(obj, 'value'); // Only objects as keys!

Expecting to Iterate WeakMap

// ❌ Cannot iterate WeakMap
const weakMap = new WeakMap([[{}, 'value']]);
// weakMap.forEach((value, key) => {}); // Error!

Simple Rules

  1. Map — universal box with any keys 📦
  2. WeakMap — magical box only with objects as keys 🧙
  3. Map can be iterated, WeakMap — cannot 🔍
  4. WeakMap cleans itself, Map — doesn’t 🗑️
  5. Use Map for general tasks, WeakMap for private data 🎯

Understanding the difference between Map and WeakMap helps choose the right tool for the job and avoid memory issues! 💪


Want more articles to prepare for interviews? Subscribe to EasyAdvice, bookmark the site and improve yourself every day 💪