cover-img

Understanding JavaScript Closure with example

20 January, 2023

8

8

1

Let us get started with the understanding of another JavaScript fundamental called Closure.

Introduction to Closure

Closure is considered an advanced concept in JavaScript. It may take a while to understand the concept fully. But, do not worry. As you have come across the fundamentals of Execution Context, Scope and Scope Chain in the previous articles of the series, it is going to be much simpler for you.

Let us start with a simple code example,

function sayHello(msg) {
return function(name) {
console.log(`${name}! ${msg}`);
}
}

Here we have a function sayHello() that takes a message as an argument. In JavaScript, functions can return another function. sayHello() returns a function that takes name as an argument and logs the name and message in the console. The function inside sayHello() is called inner function and sayHello() can be referred as an outer function.

Fair enough. How do we invoke them? Here it is,

var messageFor = sayHello('Hello, there!');
console.log(messageFor('Jack'));

As sayHello() returns a function, the variable messageFor points to a function. In the next line, we invoke messageFor() passing the value 'Jack'. It logs the following output,

Jack! Hello, there!

But, we have a few questions to ask and get clarifications about,

  • How does the inner function of sayHello() gained access to the msg variable? How is that possible?
  • What about the scope here? The msg variable is in no way in the scope of the inner function. Then how is it working?

The answer is, it is working with the help of a JavaScript feature called Closure.

A bit of recap

By now, we are aware,

  • There is something called global execution context and function execution context.
  • When a JavaScript program runs, a global execution context gets created.
  • When a function is invoked, a function execution context gets created.
  • All the function execution contexts refer to its outer environment, i.e., the execution context of the function that has created the currently running function.
  • Using the outer reference, the JavaScript engine determines the accessibility of a variable. This is called, Scoping.
  • The variable's scope can be found by traversing through the scope chain leading up to the global execution context.

We have seen this picture before, scope_chain.png

Closure anatomy

In JavaScript, a function can be nested inside another function. The nested function is called the inner function. This inner function can access the variables defined in the outer function's context. It is done by closure. So, it is the inner function that creates a closure to the outer function.

Let us understand the execution steps of the example above in more details. Here is the code again,


function sayHello(msg) {
return function(name) {
console.log(`${name}! ${msg}`);
}
}

var messageFor = sayHello('Hello, there!');

console.log(messageFor('Jack'));
  • A global execution context gets created. In its execution phase, the function sayHello() gets invoked.var messageFor = sayHello('Hello, there!');
  • A function execution context gets created for sayHello() and it gets added to the execution stack. Note, it has an argument called, msg and it will be available in its execution context. function sayHello(msg) {

    }
    • sayHello() returns another function and pop out the execution stack. function sayHello(msg) {
      return function(name) {
      console.log(`${name}! ${msg}`);
      }
      }
      But, hold on. sayHello() returns an inner function. It means, the inner function will create a closure to the outer function's(sayHello()) execution context. With that, it will also have all the access to the outer function's variables. In this case, it is msg.
  • Next, the global execution context invokes messageFor('Jack'). This is nothing but that inner function returned in the last step. console.log(messageFor('Jack'));
    This invocation will create a new function execution context. As we pass Jack as an argument, it will be available in its execution context. But remember, it also has access to the msg as explained in the step above.

This is how Closure helps retain access to the parent's execution context even when it has already been executed and removed from the execution stack.

This is a compelling concept. I hope it was simpler to understand. Not yet? Alright, let us see all these happening visually,

flow.gif

The inner function creates a special scope called Closure Scope on the outer function's execution context. This is how the closure scope will be(in red border),

closure.png

Try this example

With the explanation we have gotten so far, what do you think will be the following?

function myMultiplier(x) {
return function inner(y) {
return x * y;
}
}

and then invoke the functions like,

var multiplyOf5 = myMultiplier(5);
var multiply5x4 = multiplyOf5(4);
console.log(multiply5x4);

I'm sure you got this! Yeah, the inner function will have access to the variable of parent function's(myMultiplier()) execution context. The inner function now has two variables, i,e, x, and y, in scope.

In the execution phase, x and y have values as 5 and 4, respectively. The multiplication of these results in the value, 20. Isn't that simple now?

8

8

1

ShowwcaseHQ
Showwcase is where developers hang out and find new opportunities together as a community
Tapas Adhikary
Educator @tapaScript | Teaching JavaScript/React/FullStack | Writer | YouTuber | Founder CreoWis

More Articles

Showwcase is a professional tech network with over 0 users from over 150 countries. We assist tech professionals in showcasing their unique skills through dedicated profiles and connect them with top global companies for career opportunities.

© Copyright 2024. Showcase Creators Inc. All rights reserved.