Understand the Closure in easiest way-JavaScript

Rajesh Kumar
8 min readJun 27, 2020

We will discuss about the topic that is asked in almost every JS interview i.e Closure. Although it’s quiet easy to understand but we make it complicated by not giving proper attention and lack of knowledge. Having a proper understanding of these concepts will help you to write better, more efficient and clean code.

What is Closure in JS?

In simple words, JS closure — refers to an inner function that has access to the current scope and outer scope (enclosing) function’s variables( i.e scope chaining).

To learn more about scope and chaining you can refer this article.

Before start discuss about the closure ,let’s understand about few points:

Whenever a function is invoked, a new scope is created for that call. And when the function has finished the execution, the scope is usually destroyed.

function getMessage(name) {
let msg = "Welcome, " + name;
return msg;
}
getMessage("XYZ"); // Welcome XYZ

In the above when we invoked the getMessage function a new scope is created with new local variable and print the msg. After the execution is completed,we have no way to refer that scope again (i.e the data value state of the getMessage function).So it’s garbage collected.

Note:

i. The function scope is created for a function call, not for the function itself.

ii. Every function call creates a new scope.

Now you have the question in your mind that is there any way to access to that scope? 🤔

Answer will be yes!! We can acheive it by JS Closure.

Now let’s discuss about closure in depth with proper explanation.

Closure having access up-to three scope chaining i.e it has access to its current scope (variables defined between its curly brackets), it has access to the outer function’s variables, and it has access to the global variables

Note: The inner function has access not only to the outer function’s variables, but also to the outer function’s parameters.

To use a closure — define a function inside another function and expose it(i.e able to access it).

To expose a function — return it or pass it to another function. Let’s take the same above example with closure:-

function getMessage(name) {
let msg = `Hello ${name}`;
let sayWelcome = function(){
let fullMsg = `${msg} welcome!!`;
console.log(fullMsg)
}
return sayWelcome;
}
let welcomeMsg = getMessage("XYZ");
welcomeMsg(); // Hello XYZ welcome!!
welcomeMsg(); // Hello XYZ welcome!!
welcomeMsg(); // Hello XYZ welcome!!

In the above,we have added an inner function i.e sayWelcome inside getMessage function and expose the sayWelcome function (i.e return it so that it can accessible).When we invoked getMessage a new scope is created with it’s local variable.After execution completed it will generally destroy and welcomeMsg should throw error of undefined property.

But it will not happened in this case, because of JS closure property which is created by adding an inner function and returned it.

sayWelcome() function has it’s own local scope when it invoked after return of getMessage . After the execution of getMessage done, the scope is not destroyed in this case because sayWelcome function scope still has the reference of outer scope (i.e getMessage), so it won’t be garbage collected.

Another extremely important thing to understand is that a closure is created at every function call. Whenever I’m using the closure, it will reference the same outer scope. If any variable is change in the outer scope, than the change will be visible in the next call as well.

function displayCount(num) {let count= num;let increseCount = function() {
console.log(count);
count++;
};
return increseCount;}let getCount= displayCount(0);
getCount(); // 0
getCount(); // 1
getCount(); // 2
/* new closure - new outer scope - new count variable */
let getAnotherCount = displayCount(10);
getAnotherCount(); // 10
getAnotherCount(); // 11
/* getCount was not affected */
getCount(); // 4

In the above example,We invoked displayCount() function that creates new scope with new scope and new existed variable. If we invoked again displayCount() it will again creates new scope with new scope and new existed variable.

Let me explain the above code, we have defined a function displayCount which takes a parameter num,inside it we have initialize a variable, let count = num; and define a inner function increseCount which print the outer scope variable count and then increment it by 1.Then we have return the inner function i.e increseCount for exposing it and to acheive the Closure property.

So in simple words,we have created a function to displaying the current input number and incremented by 1 ,that takes an input number as parameter and returned the inner function.

Now we have invoked displayCount function passing 0 as input number that take it as parameter and assign it to local variable count and assign it to a variable getCount that will hold a function reference not value because displayCount return a function not value.

So after invoking displayCount and execution done,generally we are not able to get the count value again.but if you call getCount() reference variable that holds reference of outer function i.e displayCount().You will get the value of count i.e 0 because of closure property and incremented by 1 i.e 0 to 1and now if you will again call getCount you will get modified value of count i.e 1 because we know any change in outer scope variable also affect closure scope.

Now we again invoked displayCount function and assign it to new variable getAnotherCount, so a new scope will create and new closure and new variable i.e we don’t have access to previous count value i.e 3,so new parameter value i.e 10 will print when we call getAnotherCount() and so on.

But that doesn’t mean getCount got destroyed ,it still there if we again call it we will get the previous count value i.e 3.

if you want to visualize the closure value ,write console.dir(getCount) below in program .you will get the result in chrome console like that:

Now let’s demonstrate above example with image diagram: —

Now we have understood what is closure and how it works!! It’s time understand the importance of closure in JS.

Why closures are so important?

  1. Use Closure to store private data

In JS object system,it doesn’t particularly encourage or enforce to hide the information (i.e private).So most of time JS programmers take the help of coding convention rather than fully enforce the mechanism of private properties.

For example — some programmers use naming conventions such as prefixing or suffixing ‘private’ property names with an underscore character -_-. This does nothing to enforce information hiding (i.e we can still access), but it suggests to well-behaved users to not modify that property.

But Closure allow us to acheive real private data mechanism.You can choose what data to expose and what not.

let’s take an example-

function initializeCount() {
let count= 1;
let msg= "HI";
return {getCount: function() {
return count;
},
setCount: function(n) {
count = n;
}
};}let obj = initializeCount();
console.log(obj.getCount()); // 1
obj.setCount(2);
console.log(obj.getCount()); // 2

In the above ,the function returned an object which has 2 functions. Because they are properties of the object which is bound to the local scope, they are closures.

Through getCount() and setCount(), You can manipulate the count variable property but I don’t have direct access to it(i.e it’s actual value is not changes just referenced value manipulated) also we don’t have the access to msg variable it’s only change or manipulate through outer function.

2. Implement Singleton in JS using Closure

Basically, a singleton is an object that has only one instance during the whole execution of the program.

We know that every function call creates a new closure. But what if we want to prevent another call of the outer function.We can acheive it through singleton using JS.

It’s really simple,we don’t give the function name and making it immediate function by adding () at the end of function.

let mySingleton = function () {let count = 0;return {
getCount: function () {
return `Counter: ${count}`;
},
increment: function() {
count++;
}
};}();console.log(mySingleton.getCount()); //0
console.log(mySingleton.getCount()); //0
mySingleton.increment();
console.log(mySingleton.getCount()); //1
mySingleton.increment();
console.log(mySingleton.getCount()); //2

In the above, mySingleton invoke immediately function that result to access the closure property without again creating another new scope instance of outer function.

Closure lead to unexpected behaviour!!!!🤔

Sometimes,closure leads to bugs/unexpected result ,because we have access to outer function which changes also affects inner uses.For example:

function getFruitID(fruitsArray) {
let i;
let uniqueId= 100;
for (i = 0; i < fruitsArray.length; i++) {
fruitsArray[i]["fid"] = function () {
return uniqueId + i;
}
}

return fruitsArray;
}

let fruits = [{name:"Apple", fid:0}, {name:"Banana", fid:0}, {name:"Willis", fid:0}];

let createFruitID = getFruitID(fruits);

for(let k=0;k<createFruitID.length;k++){
console.log(createFruitID[2].fid()); //103
}

In the preceding example, by the time the anonymous functions are called, the value of i is 3 (the length of the array and then it increments). The number 3 was added to the uniqueId to create 103 for ALL the fruitid. So every position in the returned array get id = 103, instead of the output you are expecting i.e intended/newline 100, 101, 102.

It happened because, as we have discussed in the previous example, the closure (the anonymous function in this example) has access to the outer function’s variables by reference, not by value. So just as the previous example showed that we can access the updated variable with the closure, this example similarly accessed the i variable when it was changed, since the outer function runs the entire for loop and returns the last value of i, which is 103

To fix this side effect (bug) in closures, you can use an Immediately Invoked Function Expression (LIFE), such as the following:

function getFruitID(fruitsArray) {
let i;
let uniqueId= 100;
for (i = 0; i < fruitsArray.length; i++) {
/*the k parametric variable is the i passed in on invocation of this Immediate function*/
fruitsArray[i]["fid"] = function (k) {
return function () {
/** each iteration of the for loop passes the current value of i into this Immediate Invoke Fun and it saves the correct value to the array **/
return uniqueId + k;
} ()
/* BY adding () at the end of this function, we are executing it immediately and returning just the value of uniqueId + k, instead of returning a function.*/
} (i); // immediately invoke the function passing the i variable as a parameter
}
return fruitsArray;
}
let fruits = [{name:"Apple", fid:0}, {name:"Banana", fid:0}, {name:"Willis", fid:0}];let createFruitID = getFruitID(fruits);for(let k=0;k<createFruitID.length;k++){console.log(createFruitID[i].fid);
//100
//101
//102
}

In this case i passed as parameter and return the value not function (that’s why we are not invoking the function, only access fid as properties like createFruitID[i].fid .So after setting the value and immediate execution end the parameter reference reset for new value of k to new value of i not at their reference.

There are still many more use cases of closure in real world.Since now you have in-depth and clear understanding of closure ,you can explore it by yourself!!.

That’s it for closure !! If you really liked this article click the clap 👏button below. Also write your feedback and queries in comment section.

--

--