Closures in Javascript for beginners

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

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. I recommend you this post.

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
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!
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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.

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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.

Beware of closures when using jQuery

An event in 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
console.log(singleton.get());
console.log(singleton.get());
singleton.increment();
console.log(singleton.get());
singleton.increment();
console.log(singleton.get());
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

If you enjoyed this, please subscribe to WeeklyWebWisdom for more similar articles!

Open Source Your Knowledge: become a Contributor and help others learn. Create New Content