How do Closures work in JavaScript?

Sakshi Chaudhary
Nerd For Tech
Published in
3 min readFeb 24, 2021

--

Closures are one of the most elegant features in JavaScript. As we know, in JavaScript, functions are nothing but objects and because of this, we can do pretty amazing things with functions in JavaScript, such as passing functions as arguments to other functions. By definition, Closures are functions returned from another function. But how closures actually work under the hood is pretty magical and impressive.

So, let’s see a simple example and try to understand it:

function outer(){
let count=0;
return function(){
count++;
return count;
}
}
const result=outer();
console.log(result()); //1
console.log(result()); //2

On our console, we see 1 and then 2. Wait a minute! How does JavaScript know that count was previously incremented? Shouldn’t it give 1 again?

Let’s dive into the step-by-step execution of our code to understand what is going on behind the scenes.

First line: We declare a function named outer in our global memory. Global memory contains anything that is not defined inside a function. At this point, JavaScript only knows that outer is a function but does not know what is happening inside it because this is just the declaration.

Second line: We declare a constant named result in our global memory and store the returned value of outer in it. So we have to execute outer() now. The execution context of outer() looks something like this:

In JavaScript, each function has its own execution context, which has a local memory to store all the local variables declared in the function. Here, we have our count variable which is initialized with 0. And then as soon as we encounter the return statement, we come out of the function and the returned function from outer is stored in the constant result. After a function has returned, its execution context is destroyed and thus we no longer have access to any variable inside it. But as we can see, we are able to increment the count even without the execution context of outer(). Shouldn’t it give us an error as we do not define count in our inner function and thus there is nothing in its execution context?

Well!! Here’s the answer to this. When we return the function from outer, it’s not merely the function that is returned but also some data on the backpack of this returned function. Backpack is the term I came across to define it through a course at The FrontEnd Masters. Now, this little backpack is hidden from us and we cannot access it directly. It contains a reference to only those variables of the outer function which are used in our returned function. In our example, this backpack will have count set to 0 initially and whenever we call this function, JavaScript will update the value in this backpack. Isn’t this just mind-blowing! , we have persistent data in our global memory and to define it more technically, it is called Persistent Lexically Scoped Reference Data(PLSRD) or Close over Variable Environment.

So, that’s pretty much how closures work in JavaScript. In the real world, we can use closure in a scenario like for example, we want to calculate the 5676th term in our function. It will be a pretty expensive operation if we have to start from scratch on every function execution. So what we can do instead is, keep track of the last calculated term using closure and then next time we will have the most recent term in our backpack and we can continue from there.

Hope it helps to understand closures in JavaScript in a much better way!

Leave a clap if this helped you!

Please provide your feedback in the comments!

--

--