Open In App

Closure in JavaScript

Last Updated : 15 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Closures are a powerful and fundamental concept in JavaScript. They allow inner functions to access variables from their outer scope, even after the outer function has completed execution. In simpler terms, a closure “closes over” its lexical scope, preserving the variables and scope of the outer function. In this article, we’ll dive deep into closures, understand how they work, and explore practical examples.

What is a Closure?

closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). When you create a closure, you gain access to an outer function’s scope from an inner function. Closures are automatically created every time a function is defined in JavaScript.

Lexical Scoping

Lexical scoping refers to how a parser resolves variable names when functions are nested. The location where a variable is declared within the source code determines where that variable is available. Nested functions have access to variables declared in their outer scope. Consider the following example:

Example 1: This example shows the basic use of closure.

Javascript
function foo() {
    let b = 1;
    function inner() {
        return b;
    }
    return inner;
}
let get_func_inner = foo();

console.log(get_func_inner());
console.log(get_func_inner());
console.log(get_func_inner());

Output
1
1
1

Output:

We can access the variable b which is defined in the function foo() through function inner() as the later preserves the scope chain of the enclosing function at the time of execution of the enclosing function i.e. the inner function knows the value of b through its scope chain. 
This is closure in action that is inner function can have access to the outer function variables as well as all the global variables.

Closure in JavaScript

Closure in JavaScript

Note: Closure is the concept of function + lexical environment in which function it was created. so every function declared within another function then it has access to the scope chain of the outer function and the variables created within the scope of the outer function will not get destroyed.

Creating Closures

Now let’s look at another example. 

Example 1: Basic Closure.

Javascript
function foo(outer_arg) {

    function inner(inner_arg) {
        return outer_arg + inner_arg;
    }
    return inner;
}
let get_func_inner = foo(5);

console.log(get_func_inner(4));
console.log(get_func_inner(3));

Output
9
8

In the above example we used a parameter function rather than a default one. Not even when we are done with the execution of foo(5) we can access the outer_arg variable from the inner function. And on the execution of the inner function produce the summation of outer_arg and inner_arg as desired. 

Now let’s see an example of closure within a loop. 
In this example, we would store an anonymous function at every index of an array. 

Example 2: 

Javascript
// Outer function
function outer() {
    let arr = [];
    let i;
    for (i = 0; i < 4; i++) {
        // storing anonymous function
        arr[i] = function () { return i; }
    }

    // returning the array.
    return arr;
}

let get_arr = outer();

console.log(get_arr[0]());
console.log(get_arr[1]());
console.log(get_arr[2]());
console.log(get_arr[3]());

Output
4
4
4
4

Did you guess the right answer? In the above code, we have created four closures that point to the variable i which is the local variable to the function outer. Closure doesn’t remember the value of the variable it only points to the variable or stores the reference of the variable and hence, returns the current value. In the above code when we try to update the value it gets reflected all because the closure stores the reference. 

Let’s see the correct way to write the above code so as to get different values of i at different indexes. 

Example 3: 

Javascript
// Outer function
function outer() {
    function create_Closure(val) {
        return function () {
            return val;
        }
    }
    let arr = [];
    let i;
    for (i = 0; i < 4; i++) {
        arr[i] = create_Closure(i);
    }
    return arr;
}
let get_arr = outer();
console.log(get_arr[0]());
console.log(get_arr[1]());
console.log(get_arr[2]());
console.log(get_arr[3]());

Output
0
1
2
3

In the above code we are updating the argument of the function create_Closure with every call. Hence, we get different values of i at different indexes.

Note: It may be slightly difficult to get the concept of closure at once but try experimenting with closure in different scenarios like for creating getter/setter, callbacks, and so on. 

Common Use Cases

Closures are useful in various scenarios:

  1. Maintaining State: Closures help maintain state between events in event-driven JavaScript.
  2. Private Variables: You can create private variables by enclosing them within a closure.
  3. Callbacks and Asynchronous Code: Closures are essential for handling callbacks and asynchronous operations.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads