Diving into JavaScript Closures

Jul 27 2016

Diving into JavaScript Closures

JavaScript is an amazing programing language, it has beautiful parts. But it also contains very confusing and complex parts. Closures and scopes are probably two of the them. In his book JavaScript: The Good Parts (a must read for every web developer!) Douglas Crockford regrads the JavaScript Scope as one of the awfull parts. I couldn’t agree more. As a software developer that started his programming with languages such as C/C++, I had hard times getting used to it and prevent bugs and errors in my programs.
But where there’s a pitfall, there is also a challenge, and one of the best way to handle this challenge is using Closures.
On the contrary to scopes, Closures are one of the best features in JavaScript that adds a lot of depth and opportunities to develop clean and good code. But Closures are not easy to grasp and understand.
In this blog post I will explain what is a closure, how and when to use it.

Scope

Before jumping into Closures we must understand perfectly the JavaScript Scope and the Scope chain. Scope is the region in the code where the variable is defined.
In many languages such as C/C++, Java and more the scope of a variable is between two curly braces.
In JavaScript it is different.
The scope of a variable is within the function it was defined in. It means that we can write this code:

function foo () {
  console.log(a); //undefined
  var a = 10;
  console.log(a); //10
}

A variable that is defined outside a function will be available inside the function:

var a = 10;
function foo () {
  console.log(a); //10
}

Local variable will be available inside inner function:

function foo () {
  var a = 10;
function goo () {
console.log(a);
}
  goo(); //10
}

If a local variable is defined inside the function with the same name as an outer variable, the local variable will take precedence:

var a = 7;
function foo () {
  console.log(a); //undefined (although there is a global variable a)
  var a = 10;
  console.log(a); //10
}

ES6 (ES2015) introduced a new reserved word: let. let allows to define a blocked scope variable. This makes a lot of sense and I recommend to use it a much as possible to prevent bugs.

The scope chain and variable resolution

If a variable is being used in a function, the Javascript will execute a variable resolution: It will start by searching it in the local scope, if it is not there, it will start climbing up the function tree until it reaches the global object.
The global object is a regular JavaScript object its properties are available to all functions, in client-side JavaScript, the Window object serves as the global object.
When the JavaScript interpreter starts (or whenever a web browser loads a new page),
it creates a new global object and gives it an initial set of properties that define.

The scope chain of a function is the list of all available variables of this function. It is the scope of the function.

Closures

JavaScript uses lexical scoping, it means that the function will be executed with the variables that was in effect when the function was defined rather than the scope that was when it was invoked.

How JavaScript does it?

Javascript function contains not only the code of the function but also its scope chain.
Each time a JavaScript function is invoked, a new object is created to hold the local variables for that invocation, and that object is added to the scope chain.
The combination of the code and the scope is a closure.
The scope of all the global function are the same because they are exposed to the same variables. Nested functions have different scope, and this can lead to a very interesting implementations.
Using Closure adds a lot of power to our program, let’s see an example that demonstrate it:

I will implement a counter without a closure and indicate its limitation:

var counter = 0;
var increment  =  function () {
console.log(counter);
counter++;
}

increment();  //0
increment();  //1
increment();  //2

What is the weakness of this implementation?

The problem is that we can either change the counter variable or even change its type which can lead to bugs and errors.
 Let’s try to implement it with a closure:

var increment = function () {
var counter = 0;
return function () {
    console.log(counter);
    counter++;
  }
}
myCounter = increment();
myCounter();  //0
myCounter();  //1
myCounter();  //2

This time, the counter is in the scope of the increment function and in the anonymous nested method. When we invoke the increment(), the javascript returns the anonymous function binded to its scope chain (with counter). When we invoked myCounter(), counter is available inside and act as expected. The counter variable is available only inside the increment method, and its nested functions, no one can change it from the outside. It is much safer and robust.

How dose counter is not garbage collect after increment method is done?

As a C# or java programmers, we are used to that the variables in a function are allocated on the stack, and when the function is over they are not available anymore. In Javascript it is different. When the function returns, that variable binding object is still available if there were nested functions, only if there are no more references to the binding object it gets garbage collected.

Closures in practice

We understand that we have a powerful tool that can empower our programs. In the next section I will show some of the cases that closures really facilitate.

Encapsulation

Encapsulation is hiding private properties of our implementation from the outside world. It help us create robust programs that will not break if another code in the programs uses the same variables names.
Javascript doesn’t have out of the box encapsulation. Closures are perfect for encapsulation:

var person = function () {
  var name;
  return {
    getName: function () {
      return name;
    },
    setName: function (n) {
      name = n;
    }
  }
}

var myPerson = person();
myPerson.setName('Robert Smith');
console.log(myPerson.getName());

name is protected from outside. It is also enable us to add validation check when setting a name.

Callback and events

Closure ability to keep the scope allow to use callbacks for asynchronous functions, and also to pass parameters to it. The callback is called after it callee is ended, but the scope is still available.

var asyncCall = function (callback) {
  var message = 'callback is called';
  setTimeout(function() {
    callback(message)
  }, 1000);
};

asyncCall(function (message) {
  console.log(message);
});

Emulating private function

With closures we can implement private function that can only be called from inside another function. This is very useful for ‘hiding’ the inner implementation, and also for creating modules by using the module pattern. Example for a very simple module:

var calculator = (function() {
  return {
    add: function(a, b) {
      return a + b;
    },
    subtract: function(a, b) {
      return a - b;
    },
    multiply: function(a, b) {
      return a * b;
    },
    divide: function(a, b) {
      return a / b;
    }
  };
})();

console.log(calculator.add(1,3)); //4
console.log(calculator.subtract(5,3)); //2
console.log(calculator.multiply(2,3)); //6
console.log(calculator.divide(9,3)); //3

Generators

Closures are perfect fit for generators because the hold their state.

function sequence() {
  var count = 0;
  return function ()
  {
    return count++;
  }
}

idSequence = sequence();
console.log(idSequence ()); //0
console.log(idSequence ()); //1
console.log(idSequence ()); //2

Conclusion

JavaScript is a very interesting programing language that challenges the developers. In one hand it has a lot of pitfalls that can break the code, and in the other hand provides the developer advanced tools for creating clean and robust programs.
Closures is one of its best features. The developer can use it for many techniques and pattern and elevate his code. Encapsulations, modules and callbacks are some of the usages.
As a JavaScript developer it is very important to know how to use this tool. Understand its added you a lot of value.

References

Amitai B.
Software Developer
Back to Blog