Closures
- This lesson explains how closures work and why they are powerful.
Introduction to Closures
Closures are one of the most important and powerful concepts in JavaScript.
They are frequently asked in interviews and widely used in real-world applications, especially in:DOM event handling
Data privacy
Callbacks
Timers
Modular code
Understanding closures properly will help you write cleaner, safer, and more efficient JavaScript code.
What is a Closure ?
Simple Definition
A closure is created when a function remembers and accesses variables from its outer (parent) scope, even after the outer function has finished executing.
Technical Definition
A closure is a function that has access to:
Its own scope
Its outer function’s variables
Global variables
Even after the outer function has returned.
Why Are Closures Important ?
Closures allow JavaScript to:
Preserve data
Maintain state
Implement private variables
Control access to variables
Avoid global pollution
Understanding Closures in JavaScript
Explains how functions access and modify variables from outer scope
// Without closure (global variable)
let count = 0;
function increment() {
count++;
console.log(count);
}
increment(); // 1
increment(); // 2
Problem:
count is global
Can be modified from anywhere
Closure for Data Encapsulation and State
Uses closure to preserve and protect a private variable across function calls
function counter() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
let increment = counter();
increment(); // 1
increment(); // 2
increment(); // 3
How Closure Works
counter() is called
count is created inside counter()
Inner function is returned
counter() finishes execution
count is NOT destroyed
Inner function remembers count
This memory is called a closure.
Important Point to Remember
Even though the outer function is finished,
its variables stay alive because the inner function still needs them.
How Closure Remembers Variables Internally
Explains how inner functions retain access to outer variables even after execution
// Visual representation of closure
counter() {
count = 0 // remembered by inner function
return function () {
count++; // still accessible
}
}
- The returned function closes over the variable count.
Using Closures with Function Parameters
Creates customized functions by remembering parameter values
function multiplier(factor) {
return function (number) {
return number * factor;
};
}
let double = multiplier(2);
let triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
Each function remembers its own factor.
Closures and DOM
Closures are heavily used in DOM event handling.
Using Closures in DOM Event Handling
Maintains state across button clicks using closure
<!-- HTML -->
<button id="btn">Click Me</button>
<script>
// JavaScript
function clickCounter() {
let count = 0;
document.getElementById("btn").addEventListener("click", function () {
count++;
console.log("Clicked:", count);
});
}
clickCounter();
</script>
Here:
count is private
Only accessible through the event handler
Closure keeps it alive
Closures with let in Loops
Preserves correct values in asynchronous callbacks using block scope
for (let i = 1; i <= 3; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
// Output after 1 second: 1 2 3
let creates a new block scope automatically.
Use Cases of Closures
Data Privacy Using Closures
Protects private variables and allows controlled access through functions
function bankAccount() {
let balance = 1000;
return {
deposit(amount) {
balance += amount;
console.log(balance);
},
withdraw(amount) {
balance -= amount;
console.log(balance);
}
};
}
let account = bankAccount();
account.deposit(500); // 1500
- balance cannot be accessed directly.
Execute Function Only Once Using Closure
Ensures a function runs only once by storing state in a closure
function once() {
let executed = false;
return function () {
if (!executed) {
console.log("Executed once");
executed = true;
}
};
}
let runOnce = once();
runOnce(); // Executed once
runOnce(); // no output
- Function Factories
Create Functions Dynamically Using Function Factories
Generates customized functions by using closures with parameters
function greeting(language) {
return function (name) {
console.log(language + " " + name);
};
}
let english = greeting("Hello");
let hindi = greeting("Namaste");
english("Rahul"); // Hello Rahul
hindi("Switty"); // Namaste Switty
Closures and Memory
Closures keep variables in memory.
Poor usage can cause:
Memory leaks
Unused data retention
Best Practices for Closures
Use closures only when needed
Avoid large data inside closures
Remove event listeners when not required
Prefer let and const
Keep closures readable
Common Beginner Mistakes
Thinking closures copy values (they don’t)
Forgetting closures hold references
Overusing closures unnecessarily
Confusing scope and closure
Key Points to Remember
Closures are created automatically
Functions remember their lexical scope
Closures help in data hiding
Widely used in DOM and callbacks
Essential for advanced JavaScript