Open In App

Closure in JavaScript

Last Updated : 18 Jun, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

A closure is the combination of a function and its lexical environment, which includes variables from the outer (enclosing) function's scope. This allows the inner function to continue to access the variables from the outer function, even after the outer function has finished executing.

Closures are not functions themselves, but rather the environment that a function "remembers" when it is created. Every function in JavaScript has an associated closure, which is created at the time the function is defined. This closure allows the function to "remember" the variables in its scope at the time of its creation, even if those variables are outside the function's execution context.

Now let's understand this with the help of example

JavaScript
function outer() {
    let outerVar = "I'm in the outer scope!";
    function inner() {
        console.log(outerVar); 
    }
    return inner;  
}
const closure = outer(); 
closure();  

Output
I'm in the outer scope!

In this example

  • The function inner() forms a closure by retaining access to outerVar, which is a variable in the scope of outer().
  • Even though outer() has completed execution, inner() still has access to outerVar due to the closure.

Lexical Scoping

Closures are rely on lexical scoping, meaning that a function’s scope is determined by where the function is defined, not where it is executed. This allows inner functions to access variables from their outer function.

JavaScript
function outer() {
    const outerVar = 'I am from outer';

    function inner() {
        console.log(outerVar);
  }

    return inner;
}

const newClosure = outer();
newClosure();

Output
I am from outer

In the example above, inner() has access to outerVar because inner was defined inside outer, giving it access to the outer function's scope.

Private Variables

Closures allow a function to keep variables hidden and only accessible within that function. This is often used when creating modules to protect certain data from being accessed or modified by other parts of the program.

JavaScript
function counter() {
// Private variable
    let count = 0; 
    
    return function () {
     // Access and modify the private variable
        count++;
        return count;
    };
}

const increment = counter();
console.log(increment());
console.log(increment());
console.log(increment()); 

Output
1
2
3


Closures and IIFE

IIFEs (Immediately Invoked Function Expressions) use closures to hide data inside the function. This helps keep certain information private and prevents it from being accessed outside the function, allowing you to create self-contained modules.

JavaScript
const counter = (function () {
    let count = 0;

    return {
        increment: function () {
            count++;
            console.log(count);
        },
        reset: function () {
            count = 0;
            console.log("Counter reset");
        },
    };
})();

counter.increment(); 
counter.increment(); 
counter.reset();      

Output
1
2
Counter reset

Closure and setTimeout

Closures are helpful in asynchronous programming because they allow you to keep track of data even after a function has finished running. This is especially useful when you're working with things like timers or server requests, where the function might not run immediately.

JavaScript
function createTimers() {
    for (let i = 1; i <= 3; i++) {
        setTimeout(function () {
            console.log(`Timer ${i}`);
        }, i * 1000);
    }
}
createTimers(); 

Output

Timer 1
Timer 2
Timer 3

Closures with this keyword

Closures can be confusing when using the this keyword because this depends on how and where a function is called, not where it is defined. So, inside a closure, this might not refer to what you expect based on the function's location.

JavaScript
function Person(name) {
    this.name = name;
    
    this.sayName = function () {
        console.log(this.name);
    };

    setTimeout(function () {
        console.log(this.name); 
        // Undefined because 'this' refers to global object
    }.bind(this), 1000); 
    // Fix with bind
}

const G = new Person("GFG");
G.sayName(); 

Function Currying in JavaScript (Closure Example)

Function currying is a technique to transform a function that takes multiple arguments into a series of functions that take one argument at a time. Currying relies on closures because each of the intermediate functions has access to the arguments passed previously.

In simple words, currying allows you to create specialized functions by partially applying arguments, which are remembered through closures.

JavaScript
// Normal Function
// function add(a, b) {
//     return a + b;
// }
// console.log(add(2, 3)); 

// Function Currying
function add(a) {
    return function(b) {
        return a + b;
    };
}

const addTwo = add(2);  // First function call with 2
console.log(addTwo(3));  // Output: 5

Output
5

In this example

  • Normal Function: Directly takes two arguments (a and b) and returns their sum.
  • Function Currying: Breaks the add function into two steps. First, it takes a, and then, when calling addTwo(3), it takes b and returns the sum.

For more detail on Function Currying read the article - Function Currying

Benefits of Closures

  • Data Encapsulation: Closures enable data hiding and abstraction.
  • State Management: Retain variables between function calls.
  • Callbacks and Event Listeners: Simplify asynchronous code.

Common Pitfalls

  • Memory Leaks: Excessive use of closures may retain unnecessary references to variables, causing memory issues.
  • Performance Overhead: Overusing closures might lead to larger memory usage due to retained scopes.

Key Points

  • Closures retain access to variables from their parent scope.
  • They are heavily used in functional programming, event handlers, callbacks, and stateful functions.
  • Always be mindful of memory usage when working with closures.

Next Article
Practice Tags :

Similar Reads