Closure In Javascript


What is a Closure?
A closure is a function that remembers the variables from its outer function even after the outer function has finished executing.
Simple Definition:
"A function inside another function that can access variables of its outer function even after the outer function has executed."
Understanding with an Example
Example Without Closure:
function outerFunction() {
let message = "Hello, I am from outer function!";
}
console.log(message); // β ERROR: message is not defined
Here,
message
is a local variable insideouterFunction()
.Once
outerFunction()
runs,message
is destroyed, so we can't access it outside.
Example With Closure:
function outerFunction() {
let message = "Hello, I am from outer function!";
function innerFunction() {
console.log(message); // β
Accessing outer function's variable
}
return innerFunction;
}
const myClosure = outerFunction(); // outerFunction() executes
myClosure(); // Output: Hello, I am from outer function!
How it works?
outerFunction()
runs and createsmessage = "Hello, I am from outer function!"
.innerFunction()
is created inside it and returns tomyClosure
.Even after
outerFunction()
finishes,myClosure()
still remembersmessage
.When we call
myClosure()
, it printsmessage
even thoughouterFunction()
is already finished!
π This is a closure! The inner function remembers its outer functionβs variables.
Why Do We Need Closures?
Closures are useful in many real-world situations:
Data Privacy (Encapsulation)
Creating Function Factories
Maintaining State in Asynchronous Code
Avoiding Global Variables
Real-Life Examples of Closures
Example 1: Data Privacy (Encapsulation)
Closures help hide private data from outside access.
function bankAccount() {
let balance = 1000; // Private variable
return {
deposit: function (amount) {
balance += amount;
console.log(`Deposited ${amount}, New Balance: ${balance}`);
},
withdraw: function (amount) {
if (amount > balance) {
console.log("Insufficient funds!");
} else {
balance -= amount;
console.log(`Withdrawn ${amount}, Remaining Balance: ${balance}`);
}
}
};
}
const myAccount = bankAccount();
myAccount.deposit(500); // Deposited 500, New Balance: 1500
myAccount.withdraw(200); // Withdrawn 200, Remaining Balance: 1300
console.log(myAccount.balance); // β Undefined! balance is private
π‘ Why?
balance
is private and can't be accessed directly.It can only be modified using
deposit()
andwithdraw()
.
Example 2: Function Factory (Generating Functions Dynamically)
Closures allow us to create functions dynamically with different behaviors.
function multiplier(factor) {
return function (num) {
return num * factor;
};
}
const double = multiplier(2); // Creates a function that multiplies by 2
const triple = multiplier(3); // Creates a function that multiplies by 3
console.log(double(5)); // Output: 10
console.log(triple(5)); // Output: 15
π‘ Why?
multiplier(2)
returns a function that always multiplies by2
.multiplier(3)
returns a function that always multiplies by3
.The inner function remembers the
factor
from the outer function!
Example 3: Maintaining State in Asynchronous Code
Closures are useful when handling asynchronous operations like setTimeout
.
function counter() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
const increment = counter();
increment(); // Output: 1
increment(); // Output: 2
increment(); // Output: 3
π‘ Why?
The inner function remembers
count
even aftercounter()
is finished.Every time we call
increment()
,count
keeps increasing!
Common Interview Questions on Closures
Q1: What will be the output of this code?
function outer() {
let x = 10;
return function inner() {
console.log(x);
};
}
const closureFunc = outer();
closureFunc();
β
Output: 10
π‘ Why? The inner function remembers x
from outer()
.
Q2: What will be the output of this code?
function createCounter() {
let count = 0;
return {
increment: function () {
count++;
console.log(count);
},
decrement: function () {
count--;
console.log(count);
}
};
}
const counter = createCounter();
counter.increment(); // ?
counter.increment(); // ?
counter.decrement(); // ?
β Output:
1
2
1
π‘ Why? The count
variable persists inside the closure.
Summary of Closures
β
Definition: A closure is a function that remembers variables from its outer scope.
β
How It Works? Inner functions "close over" variables from outer functions.
β
Why Use Closures?
Data Privacy (Encapsulation)
Creating Function Factories
Maintaining State in Asynchronous Code
Avoiding Global Variables
Can You Answer These?
1. Counter with Private State Problem:
Create a function createCounter()
that returns an object with two methods:
increment()
: Increases the counter by 1.decrement()
: Decreases the counter by 1.getCount()
: Returns the current count.
Constraints:
- The count should be private and not accessible directly.
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
counter.decrement(); // 1
console.log(counter.getCount()); // 1
2. Secure Bank Account Problem:
Create a function bankAccount(initialBalance)
that returns an object with:
deposit(amount)
: Adds amount to the balance.withdraw(amount)
: Deducts amount if sufficient balance is available.checkBalance()
: Returns the current balance.
Constraints:
- The balance should be private and only modifiable through the provided methods.
const myAccount = bankAccount(1000);
myAccount.deposit(500); // Balance: 1500
myAccount.withdraw(200); // Balance: 1300
console.log(myAccount.checkBalance()); // 1300
console.log(myAccount.balance); // Undefined (Should not be accessible)
3. Function Factory Problem:
Write a function createMultiplier(factor)
that returns a function which multiplies a given number by the provided factor.
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
4. Delay Execution with Closures Problem:
Create a function delayedLogger(message, delay)
that logs message
to the console after delay
milliseconds. Use closures to retain the message value.
delayedLogger("Hello, World!", 2000); // Logs "Hello, World!" after 2 seconds
5. Event Listener with Closures Problem:
Create a function buttonClickHandler(buttonId, message)
that adds a click event listener to a button. When clicked, the button should log the provided message.
buttonClickHandler("myButton", "Button clicked!");
// Clicking the button with id "myButton" should log "Button clicked!"
Bonus Challenge
Modify the bankAccount()
function to support multiple accounts without conflicts.
Answers of Challenge
Visit my Github for see the soultion of these questions that i write ( direct link for answers)
Resources
I explore these websites, google search ai and chatgpt to explore this topic in deep.
Subscribe to my newsletter
Read articles from Giriraj lodha directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
