Skip to main content

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
  1. outerFunction defines a variable outerVar and an innerFunction.
  2. When outerFunction returns innerFunction, normally outerVar should be gone (because outerFunction finished execution).
  3. But because of closure, innerFunction “remembers” the environment in which it was created, so it still has access to outerVar

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

  1. outerFunction defines a variable outerVar and an innerFunction.
  2. When outerFunction returns innerFunction, normally outerVar should be gone (because outerFunction finished execution).
  3. But because of closure, innerFunction “remembers” the environment in which it was created, so it still has access to outerVar

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
  • count is not directly accessible from outside.
  • But increment, decrement, and getValue functions (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 var is function-scoped, all three inner functions share the same i variable.
  • By the time they run, the loop has already finished, and i is 4.

Fix using let (block scope):

for (let i = 1; i <= 3; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
// Output: 1 2 3