Codebox Software

Closures Explained

Published:

This tutorial will explain the concept of 'Closure' using small pieces of JavaScript code.

Only very basic knowledge of JavaScript is required to follow along. You should understand what functions and variables are, and should understand what is meant by 'the scope of a variable' and what a 'local variable' is.

In JavaScript, this is how you define a function:

function doubleNumber(n){
    return n * 2;
}

Another way to do exactly the same thing is like this:

var doubleNumber = function(n){
    return n * 2;
};

So when we define a function we are really defining a variable, and then assigning a function to it.

We can treat doubleNumber like any other variable, for example we can assign it to other variables:

var x = doubleNumber;

Now x is a function. We can call it just like we can call doubleNumber:

var a = x(1);            // a == 2
var b = doubleNumber(1); // b == 2

We can also make functions return other functions. Don't worry about why you would do this for now, just know that you can:

function getAFunction(){
    var doubleNumber = function(n){
        return n * 2;
    };
    return doubleNumber;
}

This will look strange if you haven't seen it before.

var fn = getAFunction();
var y = fn(1); // y == 2

We could also just do this (but probably shouldn't - it looks too confusing):

var y = getAFunction()(1); // y == 2

Ok so far? Remember that stuff about functions returning functions, we'll come back to it in a minute.

Now, have a look at this code:

function verboseFunction(){
    var x = "text";
    return x;
}

Here the variable x is redundant, we just put a value into it and then read the value straight out of it again on the next line.

We would normally just do this:

function nonVerboseFunction(){
    return "text";
}

Similarly, in our example the variable doubleNumber is redundant:

function getAFunction(){
    var doubleNumber = function(n){
        return n * 2;
    };
    return doubleNumber;
}

Getting rid of doubleNumber makes our code more concise:

function getAFunction(){
    return function(n){
        return n * 2;
    };
}

Now, what about this - we create a local variable x inside getAFunction to hold the value 2 that we use in our calculation:

function getAFunction(){
    var x = 2;
    return function(n){
        return n * x;
    };
}

Normally a local variable inside a function can only be used within that function - as soon as the function finishes the variable is gone. But in our example the doubleNumber function that we are returning needs this local variable.

Will the code still work? Yes!

function getAFunction(){
    var x = 2;
    return function(n){
        return n * x;
    };
}
var fn = getAFunction();
var y = fn(1); // y == 2

Because our 'inner' function depends on it, the variable x continues to exist even after getAFunction completes. This is called closure, it's very useful.

The variable x (and any other variables referenced by the inner function) are called upvalues of the closure.

The parameters of the outer function also form part of the closure. We can make our code above more flexible like this:

function makeMultiplierFunction(x){
    return function(n){
        return n * x;
    };
}

Now we can create functions for multiplying numbers by varying amounts:

var multiplyBy2 = makeMultiplierFunction(2);
var a = multiplyBy2(3);  // a == 6

var multiplyBy3 = makeMultiplierFunction(3);
var b = multiplyBy3(3);  // b == 9

var multiplyBy4 = makeMultiplierFunction(4);
var c = multiplyBy4(3);  // c == 12

The upvalues of the closure can be written as well as read, so a closure allows a function to remember values between invocations. Here is how to make a function that remembers how many times it has been called:

function makeFunctionThatRemembers(){
    var counter = 0;
    return function(){
        counter = counter + 1;
        return counter;
    };
}
var fn = makeFunctionThatRemembers();
var a = fn();    // a == 1
var b = fn();    // b == 2
var c = fn();    // c == 3

We could still write this function without using closures, but we would need to declare the variable counter outside the function:

var counter = 0;
function functionThatRemembers(){
    counter = counter + 1;
    return counter;
}

By declaring counter outside the function we run the risk that it will have its value changed by some other code. When we use a closure, the counter variable is hidden inside the closure, and cannot be accessed by any code outside it.

The code that we currently have is a little more verbose that it needs to be:

function makeFunctionThatRemembers(){
    var counter = 0;
    return function(){
        counter = counter + 1;
        return counter;
    };
}
var fn = makeFunctionThatRemembers();

If we only intend to run makeFunctionThatRemembers once then there is no need to actually give it a name, we can declare it and run it straight away like this:

var fn = (function(){
    var counter = 0;
    return function(){
        counter = counter + 1;
        return counter;
    };
}());

That's a lot of brackets! I'll add some colour to make things clearer

var fn = (function(){
    var counter = 0;
    return function(){
        counter = counter + 1;
        return counter;
    };
}());

The code in green is what we used to call makeFunctionThatRemembers we've just removed the name because we don't need it any more. The pair of brackets in red call the function defined in green - so we run the function as soon as we have finished defining it. The outer brackets in blue aren't strictly necessary for the code to work, but you should put them in anyway - it makes it more obvious that you are calling the function in green, not just defining it.

If you want more information about closures then try the Wikipedia article, which also shows examples of their use in other languages.