Javascript closures explained in depth

Javascript closures explained in depth

Closures are one of the key concepts of JavaScript and allow developers to write better code. Usually, they are alienated by developers who didn’t use them for years and consider that if they haven’t need them until now, they can live without them as well.

Closures are not difficult to understand but they require a paradigm change from the other mainstream languages. You have to have to look at functions and function scope with a different perspective in order to master closures.

 


Prerequisites

Since this article is focusing solely on closure, you should be familiar with execution context and function scope.

 


What is a closure?

Whenever a function is invoked, a new scope is created for that call. The local variable declared inside the function belong to that scope – they can only be accessed from that function -. It’s very important to understand that before moving further.

Remember:

  • The function scope is created for a function call, not for the function itself
  • Every function call creates a new scope

When the function has finished the execution, the scope is usually destroyed.  A simple example of such function is this:

function buildName(name) { 
    var greeting = "Hello, " + name; 
    return greeting;
}

It doesn’t get more simple than that. The function buildName() declares a local variable greeting and returns it. Every function call creates a new scope with a new local variable and. After the function is done executing, we have no way to refer to that scope again, so it’s garbage collected.

But how about when we have a link to that scope? Let’s look at the next function:

function buildName(name) { 
    var greeting = "Hello, " + name + "!"; 
    var sayName = function() {
        var welcome = greeting + " Welcome!"
        console.log(greeting); 
    }
    return sayName; 
}

var sayMyName = buildName("John");
sayMyName();  // Hello, John. Welcome!
sayMyName();  // Hello, John. Welcome!
sayMyName();  // Hello, John. Welcome!

The function sayName() from this example is a closure.

A closure is a function which has access to the variable from another function’s scope.  This is accomplished by creating a function inside a function. Of course, the outer function does not have access to the inner scope.

The sayName() function has it’s own local scope (with variable welcome) and has also access to the outer (enclosing) function’s scope. It this case, the variable greeting from buildName().

After the execution of buildName is done, the scope is not destroyed in this case. The sayMyName() function still has access to it, so it won’t be garbage collected. However, there is not other way of accessing data from the outer scope except the closure.

This is the big gotcha of the entire concept. The closure serve as the gateway between the global context and the outer scope. I cannot access directly variables from the outer scope if the closure is not allowing it. This way, I can protect the variables from the outer scope. They are – by all means – private and the closure can serve as a getter or setter for them.

Screen Shot 2017-09-24 at 8.02.02 PM

Remember:

  • Closure are nested function which has access to the outer scope
  • After the outer function is returned, by keeping a reference to the inner function (the closures) we prevent the outer scope to be destroyed.

 


Another extremely important thing to understand is that a closure is created at every function call. Whenever I’m using the closure, it will reference the same outer scope. If any variable is change in the outer scope, than the change will be visible in the next call as well.

function buildContor(i) { 
    var contor = i;
    var displayContor = function() {
       console.log(contor++);
       contor++;
    }
    return displayContor; 
}

var myContor = buildContor(1);
myContor(); // 1
myContor(); // 2
myContor(); // 3

// new closure - new outer scope - new contor variable
var myOtherContor = buildContor(10);
myOtherContor(); // 10 
myOtherContor(); // 11

// myContor was not affected 
myContor(); // 4

All three invocation of the function myContor are accessing the same outer scope, therefore the same contor variable. If one of them change it, the next call will se the value changed.

However, another call of the outer function creates a new scope, with a new contor. myOtherContor() access a totally different variable.

Remember:

  • it the variables from the outer scope are changed, it will affect the following calls

 


Why closures are so important?

Alright, now that we clarified how closures work, it’s time to see them in action. Having access to an isolated outer scope which persists data changes on successive calls is the magic of closures.

 


Use closures to store private data

Javascript’s object system does not particularly encourage or enforce information hiding. The name of every property is a string, and any piece of a program can get access to any of the properties of an object simply by asking for it by name. Features such as for...in, loops  and ES5’s Object.keys() and Object.getOwnPropertyNames() functions even make it easy to learn all the property names of an object.

Often, JS programmers resort to coding conventions rather than absolute enforcement mechanism for private properties. For example, some programmers use naming conventions such as prefixing or suffixing ‘private’ property names with an underscore character – _ -. This does nothing to enforce information hiding, but it suggests to well-behaved users to not modify that property.

Through closure, you can achieve real private data in Javascript. As we saw above, the closure is the gateway between the outer scope and the rest of the program. It can choose what data to expose and what not. Let’s see in example:

function initializeData() {
    var myVar = 1; 
    return { 
       getVar: function() {
           return myVar;
       },
       setVar: function(v) {
           myVar = v;
       }
    }
}

obj = initializeData();

console.log(obj.getVar()); // 1

obj.setVar(2);
console.log(obj.getVar()); // 2

obj.setVar("string");
console.log(obj.getVar()); // string

Here the function returned an object which has 2 functions. Because they are properties of the object which is bound to the local scope, they are closures. Through getVar and setVar, I can manipulate the myVar property but I don’t have direct access to it.

 


Use closures to create iterators

Due to the fact that the data from outer scope is preserved, creating iterators with closures is fairly easy. The buildContor() function from above it’s actually an iterator. Every call creates a new iterator with a fixed start index. Then, at every successive invocation of the iterator, the next value is returned. Check out here the full example.

 


Beware of closures when using jQuery

An Javascript jQuery (or any Javascript event) is a closure. The event handler has access to the outer scope.

$(function() { 
   var contor = 0;
   $("#myButton").click(function() { // the closure updates the variable from the outer scope
     contor++; 
   }
}

 


Implement singleton in Javascript using closures

A singleton is an object that has only one instance during the execution of a program. It is easy to achieve that in javascript once we know closures. We know that every function call creates a new closure. But what if we want to prevent another call of the outer function? It’s really simple: we don’t give the function a name.

var singleton = function () {
   var private_contor = 0;
   return {
       get: function () {
           return "Contor: " + private_contor;
   },
   increment: function() {
      private_contor++;
    }
  };
}();  // Attention Here - the singleton is the result of this function's call

This example hasn’t got big differences from the previous ones. The only difference is that the outer function is anonymous – it doesn’t have a name -. We declare it and call it right away and after that the singleton object (which is the closure) is the only source of access to its scope. This is useful when we want to make sure that there won’t be more than one scope with private_contor created.

 


Final words

I hope you agree with me by now: Closures are not hard to understand if you are looking at them in the right perspective.

Things to remember:

  • A closure is an inner function which has access to the outer function scope
  • Every call of the outer function creates a new closure
  • Every call of the closure interacts with the same outer scope – which is persistent

Thank you for your time!

Please subscribe for more weekly web wisdom!

3 thoughts on “Javascript closures explained in depth

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s