What is Closure in JavaScript? Overview & Examples

Photo of author

You may have used JavaScript many times and included it in your projects. But can you answer what closure is in JavaScript? Well, don’t worry, we have you covered. In this blog, we will talk about Closure in Javascript and its usage. 

Closure in Javascript is a critical function used every time you write a function in Javascript. Afterward, simply put the closure feature allows the inner function to approach the outer function. The closure feature is handy because it assists in retaining the state of events.

Similarly, this blog will discuss closure thoroughly, including its advantages, disadvantages, closures with loops, and some examples. Furthermore, closures are often used in Javascript Frameworks like Angular, Nextjs, Vue, etc. Moreover, this is your best guide if you need to learn closure in Javascript.

Prerequisites

Before understanding what closure is in Javascript and what its use is, you should know the following concepts: 

  • Fetch API and its applications.
  • Application of execution context in Javascript.
  • Variable Scope.

What is Closure in Javascript?

As discussed earlier, the closure feature allows the inner function to approach the outer function. Also, the closure feature is handy because it assists in retaining the state of events. Whenever you talk about closure, you will hear about lexical scoping.javascript

But what is lexical scoping? It is a procedure intended to describe the Variable’s scope by location in the source code. Lastly, Closure is a kind of lexical scoping only, yet it is distinct. Let’s discuss some examples in detail to understand this concept thoroughly.

Examples

First, let’s understand what closure is in Javascript with examples.

Example 1

Look at the following code: 

// Unique JavaScript closure example

// Outer function

function greetVisitor() {

    //Variable defined outside the inner function

    let guest name = ‘Eleanor’;

    // Inner function

    function displayGuestName() {

        // Accessing guest name Variable

        return ‘Hello’ + ‘ ‘ + guest name;

    }

    return displayGuestName;

}

const greeting1 = greetVisitor();

console.log(greeting1); // Returns the function definition

console.log(greeting1()); // Returns the value

Furthermore, the output will be:

function displayGuestName() {

      // accessing guestName variable

      return ‘Greetings’ + ‘ ‘ + guestName;

  }

Greetings Eleanor

As we can see, the greetVisitor() function is used in the above code. Furthermore, greeting1() will be used when writing the greetVisitor() function. Moreover, when the code runs, it gives back the function definition.

Example 2

Look at the following code:

// closure example

function compute(x) {

    function enhance(y) {

        return x * y;

    }

    return enhance;

}

const enhanceBy3 = compute(3);

const enhanceBy4 = compute(4);

console.log(enhanceBy3); // returns compute function definition

console.log(enhanceBy3()); // NaN

console.log(enhanceBy3(6)); // 18

console.log(enhanceBy4(2)); // 8

// Unique closure example

function execute(value) {

    function action(parameter) {

        return value * parameter;

    }

    return action;

}

const actionWith3 = execute(3);

const actionWith4 = execute(4);

console.log(actionWith3); // Returns execute function definition

console.log(actionWith3()); // NaN

console.log(actionWith3(6)); // 18

console.log(actionWith4(2)); // 8

In the above code, the execute() function is used. The execute() function grabs a single argument x and gives back the function definition of another function: enhance (). The enhance() function now grabs a single argument y and gives back x*y. Moreover, in this code, the closures are enhanceBy3 and enhanceBy4.

Furthermore, a parameter has passed x by the execute() function. Now, the enhanced function can approach the called x argument of the outer function: execute().  

Example 3

Look at the following code:

let counter = 0;

function add() {

    function increment() {

        // Increase the value of “counter” by 1.

        return counter = counter + 1;

    }

    return increment;

}

const incrementCounter = add();

console.log(incrementCounter()); // 1

console.log(incrementCounter()); // 2

console.log(incrementCounter()); // 3

counter = counter + 1;

console.log(counter); // 4

In this code, the add() function is used, which gives back the function definition of increment(). Also, the counter variable is raised within the increment() function. Moreover, we can also approach the value outside of the Variable like this: counter = counter + 1;

Pros

We now thoroughly know what closure is in Javascript. But what is the benefit of a closure in Javascript? Let’s look at some advantages of closure:

  1. Offers data encapsulation
  2. Assists in eradicating redundant code.
  3. Assists in retaining modular code.
  4. Closures keep the state by utilizing variables that can be used later on.
  5. Lastly, it permits you to fix variables in an execution context.

Cons

Let’s look at some of the disadvantages of closure:

  1. Firstly, they can decline your application if you use closures too much.
  2. The closure does not garbage collect variables announced within it.

What is Javascript Scope?

Scopes in Javascript are crucial concepts every developer should know while learning closures. It is the part of the source code where the Variable can be approached.javascript scopes

Look at the following code:

const personName=”Aaron”

console.log(personName) // Aaron

if (true) {

 let hero = “Batman” // same for const as well

console.log(hero)

}

console.log(hero); // throws ReferenceError

The above code shows that it had no difficulty approaching “personName,” but approaching “hero” showed ReferenceError. Why? It is because within the scope of the if statement, “hero” was announced or declared. Therefore, it matches the definition of scope that we mentioned earlier. Javascript has three types of scopes: 

Block Scope: By using let and const, you can scope variables to the closest code block. For example:

{

  let person2 = “Andrew” // person2 in block scope

  console.log(person2) // Andrew

}

{

  var anotherName = “Jacob” // anotherName not in block scope as var is used

  console.log(anotherName) // Jacob

}

console.log

(person2) // ReferenceError

console.log(anotherName) // Jacob

Global Scope: By the name, you must understand that the Variable can be approached anywhere in the code. For example: 

let globalName = “Andrew”

const displayGlobalName = () => {

  console.log(globalName)

}

displayGlobalName() // Andrew

console.log(globalName) // Andrew

Function Scope: In this scope, the Variable announced within the function can only be approached inside that function. Also, you cannot approach the Variable outside this scope. For example:

const showName = () => {

  const localName = ‘Andrew’ // localName defined in function scope

  console.log(localName) 

}

showName()

// trying to access localName outside the function

console.log(localName) // ReferenceError

Working on Javascript Closures with Loops

Working on Javascript closures with Loops is difficult due to its unpredictable behavior. For example, look at the following code: 

for (var identifier = 0; identifier < 3; identifier++) {

  // The setTimeout function uses a callback, and by the time the callback is executed,

  // the loop has already completed, so ‘identifier’ will always be 3 in all setTimeout callbacks.

  setTimeout(function () {

    console.log(‘seconds: ‘ + identifier);

  }, identifier * 1000);

}

We have used the setTimeout function inside a loop. The loop will run three times, and setTimeout will stand by for a particular time before running the code inside. Moreover, you would expect the output to showcase the identifier’s index value at that loop’s time like this:

“seconds: 0” “seconds: 1” “seconds: 2” 

However, that is not the case. When the loops run, the identifier variable renews accordingly. The code starts from the setTimeout function; the identifier has been renewed to its highest value by now. This happens because all three replications of the loop are divided between the same scope, and the setTimeout function builds a closure divided between each loop. So, you will get an output like this:

“seconds: 3” “seconds: 3” “seconds: 3” 

We will look at the IIFE solution and ES6 let keyword solution to solve this issue.

IIFE solution

IIFE complete form is Immediately Invoked Function Expression. This syntax urges an instant invocation of the setTimeout() immediately when the loop starts. Therefore, you don’t have to stand by for the loop to end and start the code because the setTimeout() function is already running when the loop started. The code for this will be: 

for (var identifier = 1; identifier <= 3; identifier++) {

  // Using an immediately-invoked function expression (IIFE) to create a new scope for each iteration.

  // This helps avoid the closure issue with setTimeout.

  (function (identifier) {

    setTimeout(function () {

      console.log(‘seconds: ‘ + identifier);

    }, identifier * 1000);

  })(identifier);

}

Furthermore, you will get the desired output : 

“seconds: 0” “seconds: 1” “seconds: 2” 

Javascript ES6 let Keyword.

 Another way to eradicate this issue is by using the ES6 let Keyword. Also, this solution ensures that the code inside the if block runs as desired. When you utilize the let Keyword to announce the value, a new scope is created for every loop. Look at the following code:

for (let identifier = 0; identifier < 3; identifier++) {

  // The use of ‘let’ creates a block-scoped variable, fixing the closure issue.

  // Now, each setTimeout callback captures the correct value of ‘identifier’.

  setTimeout(function () {

    console.log(‘seconds: ‘ + identifier);

  }, identifier * 1000);

}

Furthermore, you will get the desired output:

“seconds: 0” “seconds: 1” “seconds: 2”

FAQs

What is closure used for JavaScript?

Ans. The closure feature allows the inner function to approach the outer function. It is handy because it assists in retaining the state among events.

What is promise () in JavaScript?

Ans. Promise() is considered one of the most important objects in Javascript that eventually gives a single value in the future.

What is scope vs closure JavaScript?

Ans. Scopes in Javascript are the part of the source code where the variable can be approached, whereas the closure feature allows the inner function to approach the outer function.

What is a lexical scope in JavaScript?

Ans. Lexical scope is the potential of a function scope to approach variables from the parent scope.

Conclusion

In conclusion, we thoroughly learned Closure in Javascript in this blog. The closure concept and sorting in Javascript are often asked in interviews, so you should be aware of it and answer any questions that may follow. Furthermore, while working on Javascript Closures with loops IIFE and ES6, let solutions be a life-saver. Javascript has many applications. You can use Javascript in ASP.NET, or you can use Javascript to change the background color in your web projects, making it one of the most used and compatible programming languages.

Leave a Comment