Closures In Javascript
By Kartikey Yadav
javascript

Closures is an important topic when it comes to JS so let's understand it in detail

To understand closure we first need to have a good knowledge of functions and lexical scoping because closure is dependent on these concepts

To start I will explain about functions and higher-order functions so if you already know about it you can directly go to the closure part

Let's start by revising what we know about functions

We know how to call functions

  1. Normally calling a function

    function hello(){
    console.log("hi)
    }
    hello()
  2. Calling with an object

    const obj = {
    name: "Jett",
    speed() {
    console.log("Woos");
    },
    };
    obj.speed();
  3. Using the call method

    function hello(){
    console.log("hi)
    }
    hello.call()
  4. We can also use "new" operator

    const four = new Function("num", "return num");
    four(4);

We know that whenever a function is invoked it creates an execution context and that execution context consists of the "this" keyword, the "arguments" keyword, and finally the variable environment, if you want to know more about execution context do refer my article here

A important thing to know about functions is that

Functions are a special type of object which are called callable objects in JS

Why you ask, because if you imagine a box with the name of the function and some code with three properties - call, apply and bind

Function

If you now go to your text editor and type a function and then see by the intelligence you will see something like this

Functions are objects

It will give you the options or the methods that you can use with the function itself so that means it behaves like an object

Now how does this concern us, well if functions are objects then we can store them around like objects, move them and pass them to another function

Functions are first-class citizens in JS

What does that means is

1.We can store a function into a variable

var greet = function () {};

2.We can pass a function as an argument to another function

function greet(fn) {
fn();
}
greet(function () {
console.log("hello");
});
  1. We can also return a function
function greet() {
return function () {
console.log("Hi there");
};
}
greet()();

So basically what I am trying to say is function can do pretty much everything other data types can do in JS

Higher-Order Functions (HOF)

A HOF is a function that can return a function or a function that can take function as an arguments

And we also know about the lexical scoping in JS and if you don't, then you can refer to here article but in brief,

Lexical scoping or static scoping means the available variable data and functions are dependent on where the function is defined and with that we are now ready to understand the concept of closures

Closures

function hello() {
console.log("greetings");
var a = "hi";
return function b() {
var b = "hi there";
return function c() {
var c = "hello there";
return `${a} ${b} ${c}`;
};
};
}
hello()()(); // hi hi there hello there

Let's understand how the code works here

Well as you guys know that when function hello is called it is pushed onto the stack and after it returns another function it gets popped off the stack (and if a function gets popped off the stack then their variable environment gets destroyed) then function b comes onto the stack return a function and again pops off the stack

Finally, function c comes and return all the variables that were defined while in function hello and b

But didn't I just said that those functions were popped off the stack , so how does function c has the values of the variables inside it , because as we know that when ever the function gets popped off the stack we don't have access to their variable environment

And this concept of accessing the variables even if the function is popped off the stack which returning a function is called closure

Let dive deep

What happens is that the first time when the JS engine parses the code it sees that the variables are mentioned even inside the function which is being returned and so because of that it just stores the variable into a contained called closure and when the function is being called which other functions are returned then when the JS engine gets the values of the varialbes from the closure box and returns the function

Now this allows us to have uses such as memory efficiency and encapsulation

Let's see how things can be memory efficient

Memory efficient

function work(index) {
const arr = new Array(7000).fill(":)"); // create new array with 7000 elements of :)
console.log("created");
return arr[index];
}
work(55); // created
work(99); //created
work(800); // created :)

Here we have created a function that creates a new Array of 7000 elements with ":)" and finally return it, well this process takes time if we call it again and again and is not very memory efficient

What we can do instead is

function work(index) {
const arr = new Array(7000).fill(":)"); // create new array with 7000 elements of :)
console.log("created");
return function () {
return arr[index];
};
}
const workHard = work();
workHard();
workHard();
workHard();
// created :)

Here even if we call the workHard function many times it will give only one output and that saves a lot of time and memory instead of creating an array every single time on invocation

Encapsulation

Also with the help of closure, we can use encapsulation which means is a process of bundling the data (i.e. variables) and methods within the functions

We have covered the most part here , but if you think we missed something or we have some error then please suggest and give us feedback, we would love to know your thoughts and ideas

Was the article helpful? Do you have any doubts? Any topic you would like us to cover?

Reach out to us on Twitter and Instagram where we try to provide more value in threads and carousal formats

Thank You for your time

Keep learning, Keep coding :)