Closures — How & Why
A closure is a function that 'remembers' variables from its outer scope even after the outer function has finished executing. Closures power data privacy, counters, event handlers, and are one of JavaScript's most powerful and tested concepts.
Closures Explained
- Closure — A function + its surrounding environment (variables it can access)
- How — When an inner function references variables from an outer function, those variables stay alive even after the outer function returns
- Data privacy — Closures create private variables that can't be accessed directly from outside
- Common uses — Counters, factory functions, event handlers, React hooks (useState uses closures!)
- Memory — Closed-over variables remain in memory as long as the closure exists. Be mindful of memory leaks
Closures Code
// Basic closure
function createGreeter(greeting) {
// greeting is 'closed over' — remembered
return function(name) {
return `${greeting}, ${name}!`;
};
}
const hello = createGreeter("Hello");
const hey = createGreeter("Hey");
console.log(hello("Alice")); // "Hello, Alice!"
console.log(hey("Bob")); // "Hey, Bob!"
// greeting variable persists even after createGreeter returned!
// Counter with private state
function createCounter() {
let count = 0; // private — can't be accessed directly
return {
increment: () => ++count,
decrement: () => --count,
getCount: () => count,
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1
console.log(counter.getCount()); // 1
// console.log(counter.count); // undefined — count is private!
// Real-world: rate limiter
function createRateLimiter(maxCalls, period) {
let calls = 0;
setInterval(() => calls = 0, period); // reset periodically
return function() {
if (calls >= maxCalls) {
console.log("Rate limited! Try later.");
return false;
}
calls++;
return true;
};
}Tip
Tip
Closures are how React hooks work — useState, useEffect, and custom hooks all use closures to remember state between renders. Understanding closures is essential for mastering React and modern JavaScript patterns.
Closure = function + its lexical scope
Common Mistake
Warning
Closures in loops with var capture the same variable reference. for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); } prints 3,3,3 not 0,1,2. Fix: use let instead of var (block scoping creates a new i each iteration).
Practice Task
Note
Build closure-powered utilities: (1) Create a counter with increment, decrement, and getCount methods using closures. (2) Create a function multiplier(factor) that returns a function multiplying by that factor. (3) Test that the counter's internal state is truly private.
Quick Quiz
Key Takeaways
- A closure is a function that 'remembers' variables from its outer scope even after the outer function has finished executing.
- Closure — A function + its surrounding environment (variables it can access)
- How — When an inner function references variables from an outer function, those variables stay alive even after the outer function returns
- Data privacy — Closures create private variables that can't be accessed directly from outside