Closures in Javascript

Subscribe to my newsletter and never miss my upcoming articles

Hello folks!! Welcome to the next part of the series. Today we'll cover the most interesting concept in Javascript- Closures.

Many programmers use the closures in their code but may not know how things work behind the scene.

In this article, we will cover what are closures and their advantages.

So, let's dive into the concept.

What are Closures?

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).

In other words, a closure gives you access to an outer function’s scope from an inner function.

In JavaScript, closures are created every time a function is created, at function creation time.

Let's try to understand this through an example.

function outer(){
    let x = 10;
    function inner(){
        console.log(x); //output: 10
    }
    inner();
}
outer();

image.png

If you check the developer tools, then you will find out that function inner forms a closure with its lexical environment.

You can easily guess the output of the above code - output: 10.

Now take a look at another example:

function outer(){
    let x = 10;
    function inner(){
        console.log(x); 
    }
    return inner;
}
let output = outer();
console.log("output", output);
output();

image.png

In the above code snippet, the outer function returns the inner function. (function returns a function - if you are new to JS, you may find it weird, but everything is possible in javascript 😜).

If you see the output, it prints 10 to the console.

But how will it access the variable x? function inner is called outside the scope it is created and at that time there is no outer function in the call stack. Then how will it remember the variable x?

This is where closure plays an important role.

A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.

It is being able to reference a specific instance of a local binding in an enclosing scope.

A good mental model is to think of function values as containing both the code in their body and the environment in which they are created.

When called, the function body sees the environment in which it was created, not the environment in which it is called.

Now take a look at another interesting example:

function multiplier(factor){
    return number => number * factor;
}

let twice = multiplier(2);
let thrice = multiplier(3);
console.log("twice--> ", twice);
console.log("first call--> ", twice(5));
console.log("second call--> ", thrice(8));

image.png

In the above code snippet, we have defined a function multiplier(factor) that takes a single argument and returns a new function. The function it returns takes a single argument number, and returns the product of "number" and "factor".

In essence, multiplier is a function factory. It creates functions that can multiply a specific value to their argument. In the above example, the function factory creates two new functions—one that multiplies 2 to its argument, and one that multiplies 3.

twice and thrice are both closures. They share the same function body definition but store different lexical environments. In the twice lexical environment, a factor is 2, while in the lexical environment for thrice, a factor is 3.

Advantages of Closure

Not only should you know what a closure is, but you should also know why it matters, and be able to easily answer several possible use-cases for closures.

Here I'm listing some of the use-cases of closure:

  • Module design pattern
  • Object data privacy
  • Event handlers
  • Asynchronous Programming
  • Currying
  • function like once
  • Memoization

Wrap Up !!

Thanks for reading!! I hope now you understand the concept of closure. Please share it with your network. Don’t forget to leave your comments below.

Buy-me-a-coffee

No Comments Yet