🟡 MediumClosure Traps🐛 Debug Challenge

Private variable accidentally exposed

Buggy Code — Can you spot the issue?

function createWallet(initial) {
  let _balance = initial;

  return {
    _balance,  // accidentally exposed!
    deposit(amount) { _balance += amount; },
    withdraw(amount) { _balance -= amount; },
    getBalance() { return _balance; }
  };
}

const w = createWallet(100);
w.deposit(50);
console.log(w._balance); // 100 — stale! Not 150
console.log(w.getBalance()); // 150

Fixed Code

function createWallet(initial) {
  let _balance = initial; // truly private

  return {
    // Don't expose _balance at all
    deposit(amount) { _balance += amount; },
    withdraw(amount) { _balance -= amount; },
    getBalance() { return _balance; } // controlled access
  };
}

const w = createWallet(100);
w.deposit(50);
console.log(w._balance);   // undefined — truly private ✓
console.log(w.getBalance()); // 150 ✓

Bug Explained

Bug: return { _balance } copies the VALUE of _balance at creation time into the object. It's not a live reference — it's just a public property set to 100.

Explanation: Returning { _balance } copies the primitive value, creating a stale snapshot. The fix is to simply not expose it — only expose methods that access it via closure.

Key Insight: Closures provide true privacy. To keep a variable private, don't include it in the returned object — only expose methods that read/write it.

More Closure Traps Debug Challenges

🟢 Easyvar in loop — buttons all say last value🟡 MediumStale closure in React useEffect🔴 HardMemoization closure caching wrong scope🟡 MediumGenerator losing this context

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab