Javascript Closures

Have you ever been in a situation where you know a concept quite well…. that is, until you need to explain it to someone else. The process of learning through teaching can be a very powerful process. Javascript closures was one of those topics for me a few years ago. I was breezing through an interview one day when all of a sudden I was asked what a closure was. I provided the same vanilla answer I had always given, and then I was posed with a follow up question. “So tell me, if you were to pretend that I know nothing about Javascript, could you explain to me what a closure is?” The following was an answer I provided the following day.

Step 1: How can you create a closure?

Short answer: A closure is an inner function that has access to variables from outer scopes because they store references of its variables. This is possible because each closure stores the code within its scope. Let’s see how to create one in an example.

  1. In the below example, the variable has created a closure.
  2. The inner function has access to the outer functions variables. This is also an example of currying.
  3. It is not necessary to use higher order functions, we could have just created an inner function without returning it.
  4. This is also an example of pass by reference (a.k.a pass by pointer in javascript land, but I digress) and pass by value from outside of the closure. NOTE: An inner closure accessing an outer scope variable has a reference to that variable, not the value. This is true for both objects and primitives! There is an example of this further down.
var x = function (primitive, object) {
  return function (inner) {
    primitive = "CHANGED";
    object.primitive = "CHANGED";
    console.log(primitive + " - " + inner);
    console.log(object.primitive + " - " + inner);
  };
}

var primitive = "UNCHANGED";
var object = {primitive : "UNCHANGED"};
var inner = "INNER VALUE";
x(primitive, object)(inner);

console.log(primitive + " - " + inner); //Primitive is passed by value
console.log(object.primitive + " - " + inner); //Object is passed by reference

// HERE IS THE OUTPUT OF THE ABOVE CODE
CHANGED - INNER VALUE
CHANGED - INNER VALUE
UNCHANGED - INNER VALUE
CHANGED - INNER VALUE

Step 2: Which scopes will be included?

Three different scopes are included in a closure. Therefore, variables from each scope are accessible (this is where variable hoisting comes into play).

  1. Variables within the function.
  2. Variables within its containing functions.
  3. Variables from the global object.

Step 3: So… who cares!! How does this help me?

The real benefit here is that closures allow us the ability to encapsulate functionality and data within a scope, without the need to redefine each variable within each inner scope. This is especially beneficial when you consider the asynchronous functionality of javascript. I can use an inner function that will be executed on another pass of the event queue, but I can utilize the variables from my current scope simply by referencing them in my inner function

Step 4: Variables within the closure (even primitives) are referenced.

//Using Immediately Invoked Function Expression (IIFE) to create a closure with its own scope to explain this point.

var x = (function (primitive, object) {
  var scope = "UNCHANGED";
  return function () {
    return {
      setScope: function () {
        scope = "CHANGED";
      },
      getScope: function () {
        return scope;
      }
    }
  };
})();

var innerObj = x(); // Executed the function that was returned from inside the IIFE.
console.log(innerObj.getScope());
innerObj.setScope();
console.log(innerObj.getScope());

// HERE IS THE OUTPUT OF THE ABOVE CODE
UNCHANGED
CHANGED

Another example of scoping with closures

What does this print?

function foo() {
  for (var i = 0; i < 5; i++) {
    setTimeout(function () {
      console.log(i);
    }, 1000);
  }
}

This will print 4, 4, 4, 4, 4 because the inner function has a reference (not value) to the outer scope variables. And by the time I print my console logs, my reference to i is equal to 5.

If I wanted to print out 0, 1, 2, 3, 4, we could use an IIFE. The IIFE would create a new scope on each iteration.

function foo() {
  for (var i = 0; i < 5; i++) {
    (function (valueOfi) {
      setTimeout(function () {
        console.log(valueOfi);
      }, 1000);
    }(i));
  }
}

Another way to print out 0, 1, 2, 3, 4 would be to use block scoping by declaring you variable with "let".

function foo() {
  for (let i = 0; i < 5; i++) {
    setTimeout(function () {
      console.log(i);
    }, 1000);
  }
}

So that is it. I hope that you have found this post educational and that you can now explain to anyone the benefits and 'gotchas' of closures.