Closure
A closure is a feature in JavaScript (and many other programming languages) where an inner function "remembers" the variables and scope of its outer function, even after the outer function has finished executing.
In other words:
- A function inside another function forms a closure.
- The inner function can access:
- Its own variables
- The outer function’s variables
- Global variables
Why Closures Exist?
Closures happen because of lexical scoping.
- JavaScript uses lexical scope, meaning a function’s scope is determined by where it is written in the code, not where it’s called.
- The inner function keeps a reference to the outer function’s scope.
Basic Example of Clousure
function outerFunction() {
let outerVar = "I am from outer function";
function innerFunction() {
console.log(outerVar); // accessing outer function's variable
}
return innerFunction;
}
const closureExample = outerFunction();
closureExample(); // Output: I am from outer function
outerFunctiondefines a variableouterVarand aninnerFunction.- When
outerFunctionreturnsinnerFunction, normallyouterVarshould be gone (becauseouterFunctionfinished execution). - But because of closure,
innerFunction“remembers” the environment in which it was created, so it still has access toouterVar
How It Works
- Closure creates due to lexical scoping
- Child function can access everything from parent function due to closure
- We want to return something which required something which is not in its scope, in its parent scope
- That's why all the required things packed up and return together and we can access it
Closure passing argment to child
function outerFunction() {
let outerVar = "I am from outer function";
function innerFunction() {
console.log(outerVar); // accessing outer function's variable
}
return innerFunction;
}
const closureExample = outerFunction();
closureExample(); // Output: I am from outer function
outerFunctiondefines a variableouterVarand aninnerFunction.- When
outerFunctionreturnsinnerFunction, normallyouterVarshould be gone (becauseouterFunctionfinished execution). - But because of closure,
innerFunction“remembers” the environment in which it was created, so it still has access toouterVar
How It Works
- Closure creates due to lexical scoping
- Child function can access everything from parent function due to closure
- We want to return something which required something which is not in its scope, in its parent scope
- That's why all the required things packed up and return together and we can access it
Closure passing argment to child
function parent(a) {
function child(b) {
console.log(`Sum: ${a + b}`);
}
}
parent(6)(4);
Closure with Private Variables
function createCounter() {
let count = 0; // private variable
return {
increment: function () {
count++;
console.log(count);
},
decrement: function () {
count--;
console.log(count);
},
getValue: function () {
return count;
},
};
}
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
counter.decrement(); // 1
console.log(counter.getValue()); // 1
countis not directly accessible from outside.- But
increment,decrement, andgetValuefunctions (inner functions) can access and modify it because of closure. - This mimics private variables in JavaScript.
Closure in Loops
for (var i = 1; i <= 3; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
Output after 1 second:
4
4
4
- Because
varis function-scoped, all three inner functions share the sameivariable. - By the time they run, the loop has already finished, and
iis4.
Fix using let (block scope):
for (let i = 1; i <= 3; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
// Output: 1 2 3