🎒 JavaScript Closures

A function that "remembers" its outer scope even after the outer function has returned

A closure is formed when an inner function references variables from its outer (enclosing) function's scope. Even after the outer function finishes executing, the inner function keeps a live reference to those variables. It's like carrying a backpack with the outer scope's variables wherever the function goes.
function makeCounter() {
  let count = 0;  // outer scope var
  
  return function increment() {
    count++;           // captures 'count'
    return count;     
  };                 // ↑ this is the closure
}
 
const counter1 = makeCounter();
const counter2 = makeCounter();
 
counter1(); // 1
counter1(); // 2 — same 'count' variable!
counter2(); // 1 — separate closure, separate 'count'
👆 Each call to makeCounter() creates a new scope with its own count. The returned function closes over that specific scope. counter1 and counter2 have completely independent memory.

🔭 Scope Chain Visualization

Global Scope
counter1=fn()
counter2=fn()
Closure Scope of counter1
count=0
increment fn body
count++ → reads outer scope ↑
Closure Scope of counter2
count=0
🎒
The Closure "Backpack"
Click the counter buttons to see closures in action

🎮 Interactive Counter Demo — See Independent Closures

counter1 instance
0
count in memory: 0
counter2 instance
0
count in memory: 0
counter3 instance
0
count in memory: 0
👉 Press any counter — notice how each one maintains its own private count. That's the power of closures: private state without classes!

🧩 Real-World Closure Use Cases

🔒 Data Privacy
Closures let you create private variables — only the returned function can access them. No class needed.
⏱ Memoization
Cache expensive results in a closure scope. Future calls check the cache before recomputing.
🎨 Event Handlers
React's onClick handlers close over state and props. useState updates work because of closures.