JavaScript Notes
Learn JavaScript closures deeply – lexical scope, scope chain, private variables, closure memory, loop bugs, React hooks, and real-world patterns with interview Q&A.
Introduction
Closures are one of the most important — and most asked-about — concepts in JavaScript. They're behind how private variables work, how callbacks remember their context, how React hooks maintain state, and how many advanced patterns like debounce, memoization, and currying are built.
Once you truly understand closures, a huge part of JavaScript's behavior will start making sense.
Why Closures Exist – Lexical Scoping
JavaScript uses lexical scoping — a function's accessible variables are decided by where the function is written in the code, not where it is called.
LEXICAL SCOPING RULE:
A function can always access variables from:
1. Its own local scope
2. Any outer (enclosing) function's scope
3. The global scopeThis is the scope chain.
Scope Chain Diagram
let globalVar = "global";
function outer() {
let outerVar = "outer";
function inner() {
let innerVar = "inner";
console.log(innerVar); // ✅ own scope
console.log(outerVar); // ✅ outer scope (closure)
console.log(globalVar); // ✅ global scope
}
inner();
}
outer();inner outer global
Basic Closure Example
function createGreeting(name) {
return function greet() {
return `Hello, ${name}!`;
};
}
const greetRiya = createGreeting("Riya");
const greetArjun = createGreeting("Arjun");
console.log(greetRiya());
console.log(greetArjun());Hello, Riya! Hello, Arjun!
Step-by-Step Explanation:
Memory Diagram – How Closures Are Stored
Each closure has its own private environment. They don't share variables.
Example 1: Counter with Private State
Closures allow you to create private variables — data that can't be accessed or modified from outside.
1 2 1 1 undefined
Example 2: Function Factory
function multiplyBy(factor) {
return function (number) {
return number * factor;
};
}
const double = multiplyBy(2);
const triple = multiplyBy(3);
const tenTimes = multiplyBy(10);
console.log(double(5)); // 5 × 2
console.log(triple(4)); // 4 × 3
console.log(tenTimes(7)); // 7 × 1010 12 70
Each function remembers its own factor through closure.
Example 3: Closure in Event Handlers
"Save" clicked 1 time(s) "Save" clicked 2 time(s) "Delete" clicked 1 time(s) "Save" clicked 3 time(s)
Each button has its own private clickCount through closure.
Example 4: Memoization Using Closure
25 From cache: 5 25 100
Real World Analogy
Think of closures like a backpack a function carries. When a function is created inside another function, it packs a "backpack" with all the variables from the outer scope that it needs. Even when the outer function is gone (returned, finished), the inner function still has its backpack with everything it needs. 🎒greetRiyacarriesname = "Riya"in its backpack. 🎒greetArjuncarriesname = "Arjun"in its own backpack.
Common Mistakes
❌ Mistake 1: Thinking Closures Copy Values (They Don't — They Reference)
function demo() {
let value = 1;
const show = function () {
console.log(value); // references `value`, not a copy!
};
value = 99; // changing value after show is created
return show;
}
const fn = demo();
fn(); // what prints?99
The closure references the variable itself, not its value at creation time.
❌ Mistake 2: The Classic var Loop Bug
4 4 4
All three callbacks close over the same i (because var is function-scoped). By the time they run, the loop is done and i = 4.
1 2 3
With let, each iteration gets its own closure over a distinct i.
❌ Mistake 3: Stale Closure (Common in React)
function createLogger(count) {
// captures the `count` PARAMETER value, not the outer variable
return function log() {
console.log(count);
};
}
let count = 0;
const log = createLogger(count); // passes 0 as argument
count = 5; // this changes outer variable, NOT the closure's copy
log(); // logs the parameter value, not outer count0
The closure captured count as a parameter (a copy of 0), not a reference to the outer count variable.
❌ Mistake 4: Memory Leaks from Unnecessary Closures
Fix: Only retain what you actually need.
Scope Chain Lookup — How JavaScript Finds Variables
When `inner()` uses a variable, JS looks in this order:
1. inner's own scope → found? ✅ use it
2. outer's scope → found? ✅ use it
3. global scope → found? ✅ use it
4. Not found anywhere → ❌ ReferenceError
This chain of scopes = SCOPE CHAINClosures vs. Global Variables
| Approach | Accessible From | Risk |
|---|---|---|
| Global variable | Everywhere | Easily overwritten by any code |
| Closure variable | Only through returned functions | Safe, controlled access |
Closures are the safer alternative to globals for shared state.
Comparison Table
| Concept | Meaning |
|---|---|
| Lexical Scope | Variables accessible based on code location |
| Scope Chain | The lookup chain from inner to outer to global |
| Closure | Function + its remembered outer environment |
| Private State | Data accessible only via controlled functions |
| Stale Closure | Bug when closure has outdated variable snapshot |
Interview Questions
Q1. What is a closure in JavaScript?
A closure is a function that retains access to variables from its outer lexical scope even after the outer function has finished executing.
Q2. How is closure different from scope?
Scope is the set of variables accessible at a given point in code. A closure is a specific mechanism where a function *carries* its outer scope's variables even when executed outside that scope.
Q3. Do closures copy variables or reference them?
They reference variables. If the variable changes, the closure sees the updated value (unless it was captured as a parameter/copy).
Q4. Explain the var loop closure bug and how to fix it.
var is function-scoped, so all loop iterations share one i. Use let (block-scoped) to give each iteration its own binding, or wrap in an IIFE.
Q5. Can closures cause memory leaks?
Yes. If a closure keeps a reference to a large object, that object won't be garbage collected. Solution: only capture what's needed.
Q6. What is a function factory? How do closures enable it?
A function factory is a function that creates and returns other functions customized by its parameters. Closures enable factories by letting each returned function remember its own outer variable values.
Q7. What is a stale closure?
A stale closure is when a closure captures an outdated variable value, common in React hooks with async operations. The function uses the value from when it was created, not the current value.
Q8. How are closures used in the module pattern?
1000 undefined
Key Takeaways
- ✅ A closure = a function + its lexical environment (remembered outer variables)
- ✅ No special syntax — closures happen naturally with nested functions
- ✅ Closures reference variables, not copies (except when captured as parameters)
- ✅ Each closure instance has its own private environment
- ✅ Use closures for private state, factories, memoization, module patterns
- ✅ Use
let(notvar) in loops to avoid the shared-variable bug - ✅ Be careful of large object retention in closures (memory leak)
- ✅ Stale closures are a common React bug — understand what was captured and when
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript Closures Explained – Lexical Scope, Private State & Memory.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, functions, closures, javascript closures explained – lexical scope, private state & memory
Related JavaScript Master Course Topics