Understanding JavaScript Closures

Closures can be quite tricky to understand especially for beginners. They are one of the most powerful features of JavaScript but they cannot be properly exploited without understanding them.

Closures are objects that contain a function and a reference to the environment in which the function was created. They are language construct, which allows to preserve the state of the variables and so prolong the scope.

Let’s look at a basic example:

Screen Shot 2017-10-31 at 21.32.20

Here, the function reference variable newFunc references to both the function that alerts and to its closure. The inner function sayHello() has access to the containing functions variables.

Module Patterns

In JavaScript, we can simulate private methods using closures. Private methods that are only accessible by other functions created within that closure. Functions can be attached to an object and returned outside of that function call. This establishes a public API and only the functions defined within that public API will have access to those hidden functions.

Let’s look at the following example:

var myCounter = (function() {

  var count = 0;

  //private

  function sum(val) {

    count += val;

  }

  return {

    //public

    increment: function() {

      sum(1);

    },

    value: function() {

      return count;

    }

  };  

})();

myCounter.increment();

myCounter.increment();

console.log(myCounter.value()); //2

Here, the function sum() cannot be accessed from outside the wrapper function myCounter(). The returned object has references to function sum(), which in turn has access to “private” variable count.

Using Closures in loops

Consider the following example.

for(var i = 1; i <= 3; i++) {

   setTimeout(function() {

       console.log(i);

   },1);

}

When we run the above code, we get the following output:

4

4

4

Here, var defines variable globally, or locally to an entire function regardless of block scope.

The problem is that the closure scope for each anonymous function at each iteration of the loop points to the same variable, the same location in memory. All of them point to a same variable i. When 1 millisecond pass and the callback functions begin to run they all look for the variable i on their outer function scope. All the callback functions share the same outer function scope that has single i variable which is now 4, where 4 is the number that finally breaks the loop.

One of the ways to solve this problem is to make use of let introduced in ES6. We can write the above code as follows:

for(let i = 1; i <= 3; i++) {

   setTimeout(function() {

       console.log(i);

   },1);

}

Here, let defines the variable in block level scope. When we run this code, we get output as follows:

1

2

3

Wrapping up

Closures are powerful programming constructs for achieving binding between code and data in a more flexible and out-of-bounds manner. They make code more compact, readable and promote functional re-use.

 

3 thoughts on “Understanding JavaScript Closures

Discussion