Saturday, April 25, 2020

JavaScript Closures

JavaScript Closures


An inner function always has access to the members of its outer function, even after the outer function has returned. When a function is bundled (nested) with references to its outer (nesting) environment is known as closure. It means a closure provides a way to access the scope of the outer function from an inner function. A closure is constructed every time when a function is created. In JavaScript, the global variables can be made local with closures.

JavaScript programmers come across situations when they use closures knowingly or unknowingly.

    function outer() {
      var message = 'JavaScript closure'; // variable in the outer scope
      function displayMessage() {
      // displayMessage() is the inner(nested) function, a closure
      document.write(message); 
      // variable message is declared in the parent function
      }
      displayMessage();
    }
    outer();


In the example, the function outer() contains a local variable message and a nested function displayMessage(). The displayMessage() function is an inner(nested) function that is defined inside outer(), and is available only within the body of the outer() function. However, the displayMessage() function has no local variables declared within itself. Since, the inner (nested) function has the access to the variables of outer(nested) function, the displayMessage() function has the access to the variable name defined in the parent function, outer() function.

JavaScript Closures
JavaScript Closures


// same effect as above code  
     function outer() {
      var message = 'JavaScript Closures';
      function displayMessage() {
        document.write(message);
      }
      return displayMessage;
    }
    var msg = outer();
    msg();

This script has the same results as the previous example of the outer() function above. The difference is that the displayMessage() function is returned from the outer function before it is executed.


     function addOperation(x) {
      return function(y) {
        return x + y;
      };
    }

    var add2 = addOperation(2);
    var add4 = addOperation(4);

    document.write(add2(2)); // 4
    document.write('<br>');
    document.write(add4(2)); // 6


The function addOperation(x) takes an argument x, and returns a new function. The returned function is also passed an argument y. The inner function returns the addition of x and y.

Basically, the addOperation works as a function factory. It produces and supplies functions after adding a supplied value with its argument. This function factory creates two new functions, first to add 2, and second adds 4. Add2 and add4 are two closures and share the same function body definition.

Emulating private methods with closures


In many programming languages like Java, we can define methods as private. These methods can be called only by other methods within the same class. 

In JavaScript, there is no natural way to create private methods. However, we can create methods that can emulate private methods using closures. Private methods are very useful in access control in the code. The global namespace can also be managed by private methods efficiently. 

For example,

     var myCounter = (function() {
      var privateCount = 0;
      function changeBy(v) {
        privateCount += v;
      }

      return {
        next: function() {
          changeBy(1);
        },

        prev: function() {
          changeBy(-1);
        },

        val: function() {
          return privateCount;
        }
      };
    })();

    document.write(myCounter.val()+'<br>');  //output 0

    myCounter.next();
    myCounter.next();
    document.write(myCounter.val()+'<br>');  //output 2

    myCounter.prev();
    document.write(myCounter.val()+'<br>');  //output 1