JavaScript Closures – The only concept to define Private Data in JavaScript

Free Web development courses with real-time projects Start Now!!

JavaScript provides us with a lot of freedom in terms of functions. We can dynamically create a function, copy it to another variable, call it from a different place in your program or pass it as a parameter to another function. We can access variables defined inside (local variables) as well as outside the function. But what happens when the value of the variable changes during execution? Or if multiple functions access the same variable and one of them changes the value? Our code will be in shambles, and this will lead to unwanted results. How to solve this? The answer to that question is JavaScript Closures. You don’t have to know JavaScript closures as a beginner. But, if you wish to get an in-depth understanding of how JavaScript works, this topic is crucial for you. Understanding the working of any programming language is better than learning the syntax. It gives you better tools when you encounter an error or when you want to perform debugging.

Before moving further, please complete the JavaScript Regular Expression Tutorial

The Lexical Environment in JavaScript

Every time you create a scope in your program with the help of the curly braces { }, you create an internal (hidden) associated object called a lexical environment. It can be defined with a running function, code block, or an entire script. It is a logistical concept, and there is no way to access it from your JavaScript code. There are two components of a lexical environment:

  • Environment Record – This is the object that stores all the local variables as its property.
  • A reference to the outer lexical environment (binds the outer code).

You need to remember that when the code wants to access a variable, it starts from the inner lexical environment (inner scope of the local variables), then moves outwards to the outer lexical environment. It finishes its search after it goes through the global lexical environment.

Problems with Function Scope

Many a time, it happens that we modify the value of a variable in our program during execution. Also, some functions use the same variables. So the question that arises here is this: When we change the variable value, does the value in the function changes too? Let’s find out with the help of some simple codes that present us with different situations.

Situation 1: When we use a global variable in the function.

Code:

<html>
    <body>

        <script>
            let count = 0; // global variable declared
            function sayHello(){
                count++; //increments the value of the global variable
            }
            sayHello();
            document.write("Hello DataFlair.</br> Counter: " + count + "</br>");
            count = 7; // global variable redeclared
            sayHello(); // uses redeclared variable name
            sayHello();
            document.write("Counter: " + count + "</br>");
        </script>

    </body>
</html>

Screenshot:

using global variable in function - JavaScript Closures

Output:

using global variable in function output

Oops! Something went wrong, didn’t it? We wanted to count how many times we called the function sayHello() using a global variable that stores its value. Instead, the last line in our output suggests that we accidentally incremented the redeclared variable of the global variable. Let’s try again. But this time, we’ll use a local variable to do that for me.

Situation 2: When we use a local variable in the function.

Code:

<html>
      <body>

          <script>
                  document.write("Using local variables:</br>")
                  function Counter(){
                      let count = 0; // local variable declared
                      count++; // increments the value of the variable
                      return function(){
                              document.write("Counter: " + count + "</br>");

                      }

                  }

                  var myFunction = Counter();
                  myFunction();
                  myFunction();
                  myFunction();
          </script>

      </body>
</html>

Screenshot:

using local variable in function code

Output:

using local variable in function output

Okay, that really wasn’t the output I wanted. What happened? Well, we used the local variable in our function, which resets every time a function returns. Thus after each function call, the count returns to zero.

The problem with the above functions was that we misinterpreted the function scope. What we need to understand is that during a function invocation, the script creates a new scope for that call. Thus, we need to remember that the function scope is for a function call, rather than the function itself.

Well, these two approaches failed, big way. But wait, don’t be disappointed, JavaScript has something for you to solve this problem just right: Closures.

Wait a minute! Have you learned about JavaScript Variable Declaration

What are JavaScript Closures?

In the above problem, we need to create ‘private’ variables for a function in a way that they don’t reset after the function returns. We can achieve the desired output with the help of closures. A closure is a combination of a function and the lexical environment where we declared the variable. It can access the parent scope even after the parent function closes. This environment contains any local variables that were in-scope at the time of closure creation. You might be wondering how that is possible, right?

Closures make use of self-invoking functions in JavaScript. Since these functions run only once, they set the values of the variables and then returns a function expression. The important fact is that they are “nested functions”, thus they can access the outer variables (variables in the parent scope). Let’s understand this approach with the help of an example.

Situation 3: When we use a closure.

Code:

<html>
    <body>

        <script>
            document.write("DataFlair: Using Closures</br>")
            function Counter(){
                let count = 0; // local variable declared

                return function(){
                        count++; //increments the value of the variable
                        document.write("Counter: " + count + "</br>");
                }

            }
            var myFunction = Counter();
            myFunction();
            myFunction();
            myFunction();

        </script>

    </body>
</html>

Screenshot:

Using JavaScript Closures Code

Output:

Using JavaScript Closures Output

In this example, the count is protected by the scope of the anonymous, and we can only alter it while using the Counter() function. The program below makes the working of a closure a little more clear.

Code:

<html>
    <body>

        <script>
            function addNumbers(num1){ //closure
                return function(num2){
                    return num1 + num2;
                };
            }
            // calling the outer function for num1
            var add20 = addNumbers(20);
            var add30 = addNumbers(30);
            // calling the inner function for num2
            document.write("Sum1:</br>20 + 30 = " + add20(30) + "</br>");

            document.write("Sum2:</br>30 + 70 =  " + add30(70) + "</br>");
        </script>

    </body>
</html>

Screenshot:

Using JavaScript Closures Code 2

Output:

Using JavaScript Closures Output 2

Notice that the parent function for add20 and add30 returned before we accessed the inner functions. It is because both of them are closures, saving the parent properties. Thus, we got the exact output we wanted. Try doing that with the help of a regular function and compare the two outputs.

Determining whether a given Function is Closure or not

Alright, we learned how to define a closure in our program. Now, we will find out whether a given function is a closure or not? Is there any way you can differentiate them from a normal function? Yes, there is. You can do that by noticing the inner function. Can you access the inner function directly? Do you have the means to call the nested function without its parent function? If the answer is no, then my friend, you’ve got a JavaScript closure.

It is because, in a closure, you can access an inner function only with the help of its parent function. It prevents an unauthorized user from accessing all the properties of the closure. In other programming languages like Java, we use access modifiers to define private properties in a class. Since we don’t have such a keyword available in JavaScript, we use closures.

Remember, you will often see that the inner function is anonymous. The reason is that it works as a wrapper around the code you want to protect from outer access.

Time to revise the different types of JavaScript Functions

Why are JavaScript Closures so important?

Closures are very useful when you want to define private properties in JavaScript. Some programmers prefix private properties with an underscore (_), indicating that you should not modify that property. But this does nothing to implement information hiding, rather gives the warning to be careful while using these values. On the other hand, closures are like a welcome mat between the outer scope and the rest of the program. They are magical since they allow us to achieve private data in JavaScript.

The problem in JavaScript Closure Loop 

Before the introduction of ECMAScript 2015, there was a common problem while using closures with loops. The problem is clear from the code below.

Code:

<html>
    <body>
        <script type="text/javascript">
                var variables = []; //creating an empty array
                for (var iterator = 0; iterator < 3; iterator++) {
                    //adding values to the array (closure)
    variables[iterator] = function() {
        console.log("My value: " + iterator);
    };
  }
  //iterating through each value in the array
  for (var iterator2 = 0; iterator2 < 3; iterator2++) {
      variables[iterator2]();
  }
        </script>
    </body>
</html>

Screenshot:

closure loop problem

We expected the value as follows:

My value: 0

My value: 1

My value: 2

The output we get is, as shown below:

closure loop problem output

Unexpected, wasn’t it? The problem lies with the variable declaration. There are two ways you can solve this problem. First, you can change the name of the iteration variable of the second loop so that it doesn’t always run with the value 3 (set by the previous for loop). Another approach you can use in modern browsers is the use of ‘let’ keyword for variable declaration. It prevents the continuous changing of the variable’s value and gets the desired output.

Output:

closure loop problem solution output

Do you know about JavaScript Loop Control Statements

Much better now, and just what we wanted the output to be. Experiment with this code and other codes where you use closures inside a function. You need to practice numerous problems to master the concept. If you get stuck, come back to the JavaScript closures tutorial and try to find out the problem when you get stuck. 

Summary

In this tutorial, we learned a lot about JavaScript closures. We discussed the various problems with a normal function and how JavaScript closures help in that case. We also reviewed why we need closures in our JavaScript program.

Thinking, what to learn next? Here is the JavaScript Garbage Collection Tutorial for you.

Feedbacks and suggestions for us? Mention them in the comment section of JavaScript Closures Tutorial. We will be glad to hear from you. Keep visiting DataFlair for regular updates.

Happy Learning!

Did you like this article? If Yes, please give DataFlair 5 Stars on Google

follow dataflair on YouTube

Leave a Reply

Your email address will not be published. Required fields are marked *