🔴 HardClosure Traps🐛 Debug Challenge

Memoization closure caching wrong scope

Buggy Code — Can you spot the issue?

const cache = {};

function memoize(fn) {
  return function(...args) {
    const key = JSON.stringify(args);
    if (cache[key] !== undefined) {
      return cache[key];
    }
    const result = fn(...args);
    cache[key] = result;
    return result;
  };
}

const double = memoize(x => x * 2);
const triple = memoize(x => x * 3);

console.log(double(5)); // 10
console.log(triple(5)); // should be 15, but gets 10 from shared cache!

Fixed Code

function memoize(fn) {
  const cache = {}; // each memoized fn gets its OWN cache

  return function(...args) {
    const key = JSON.stringify(args);
    if (cache[key] !== undefined) {
      return cache[key];
    }
    const result = fn(...args);
    cache[key] = result;
    return result;
  };
}

const double = memoize(x => x * 2);
const triple = memoize(x => x * 3);

console.log(double(5)); // 10 ✓
console.log(triple(5)); // 15 ✓

Bug Explained

Bug: cache is declared outside memoize — all memoized functions share one global cache. double(5)=10 gets cached, triple(5) finds cache[5]=10 and returns it.

Explanation: Moving cache inside memoize creates a fresh cache per call via closure. Each memoized function closes over its own private cache object.

Key Insight: Closures for encapsulation: state declared inside a factory function belongs exclusively to each returned function.

More Closure Traps Debug Challenges

🟢 Easyvar in loop — buttons all say last value🟡 MediumStale closure in React useEffect🟡 MediumPrivate variable accidentally exposed🟡 MediumGenerator losing this context

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab