JavaScript Closures

Before learning about closures you should make sure you know about general scopes and about JavaScript scope.

What Are They?

Books will probably tell you that they are 'stateful functions'. Which is true. But what does that mean?

It means that the functions remember everything that WAS in their scope at the time of their definition. In JavaScript you will use these all of the time. You will, in fact, have a hard time not using them regardless if you intend to or not.

They can be extremely powerful and understanding them will be crutial to becomming a good JavaScript developer.

A Very Basic Walkthrough

Lets start out with a function that returns a function.

function counter() {
    // Now inside this scope we will define a variable we will use to count.
    var current_val = 0;

    // Now we are going to return a function that uses this value.
    return function() {
        return ++current_val
    };
}

var counter1 = counter();
var counter2 = counter();
console.log(counter1()); // We will get '1'.
console.log(counter1()); // We will get '2'.
console.log(counter2()); // We will get '1'.
console.log(counter2()); // We will get '2'.
console.log(counter1()); // We will get '3'.

So what is going on here? This is a classic example of a closure.

Going over this code again:

// Below when we run:
// var counter1 = counter();
// This runs the following counter() function and sets counter1
// to its return value.

function counter() {
    // Every call of a function gets its own scope so we are inside
    // a new scope and declare our current_val variable.
    var current_val = 0;

    // Now our return value is going to be a function which is a bit
    // weird to think about until you realize that a function is just
    // a type of data you can store in a variable too.
    return function() {
        // This will be referencing the 'current_val' that is presently
        // in scope.  The one that is in scope right now as of the time
        // of defining this function.
        return ++current_val
    };
    // As of the return statement we are closing the scope of counter().

    // Our variable 'counter1' will now equal:
    // function() {
    //     return ++current_val
    // };
}

// Now we do the actual asignment like mentioned above.
var counter1 = counter();

// So now when we call counter1() it runs:
// function() {
//     return ++current_val
// };

// It takes the value of current_val from its scope which is 0, increments
// it by one and returns the value.

console.log(counter1()); // Returns '1'.

// Ok, that's fine and dandy but I want to make that current_val
// to jump a few numbers so I'm just going to overwrite it.
current_val = 9;

// Now lets try.
console.log(counter1()); // Returns '2'.

// WTF?! That's right. It is still using the current_val variable in its closest
// scope which is the scope in which its function was defined.  Even though that
// scope is technically closed at this point it remains as part of the function
// that was returned.

// Maybe we just need to scope this instead of making it global.
var current_val = 9;
console.log(counter1()); // Returns '3'.

// Then why does creating a new one work?
var counter2 = counter();
console.log(counter2()); // Returns '1'.

// That is because when we run counter() and go into the function we are
// creating a new scope.  Creating a new current_val as 0 and returning a
// new function in that new scope.

// So counter2's current_val that is in scope was 0 and is now 1
// and counter1's current_val that is in scope is current 3.

It is a bit mindblowing right? That is the essence of a closure.

A More Complex Walkthrough

Now, lets use a closure in a way that we can allow multiple objects of the same type talk to themselves.

var my_obj_constructor = (function(){

    var my_siblings = [];

    return function(obj_name) {
        this.name        = obj_name;
        this.my_siblings = my_siblings

        my_siblings.push(obj_name);
    }
})();

var obj_1 = new my_obj_constructor('obj1');
var obj_2 = new my_obj_constructor('obj2');
var obj_3 = new my_obj_constructor('Shaflibble');

console.log(obj_1.my_siblings); // Returns: ['obj1', 'obj2', 'Shaflibble']

So how is it that obj_1 can see the rest of the obj's? Lets boil down what is happening.

var my_obj_constructor = (function(){
    // ...  Stuff here.
})();

What is this sorcery?!!! Wrapping something in parens doesn't do a whole lot but imagine it as storing the value in an anonymous variable and then immediately returning it. For example:

var a = ("a");
// Is the same thing as:
var a = "a";

var f = (function() { return "a"; });
// Is the same thing as:
var f = function() { return "a";  };

// However if we want 'f' to equal the results of that function we would do:
var f = (function() { return "a"; })();
// Technically the following works but could be more erratic:
var f = function() { return "a"; }();

Extrapolating from that, here is another way to express what we are doing in the original constructor.

var ANONYMOUS_VARIABLE = function() {

    var my_siblings = [];

    return function(obj_name) {
        this.name        = obj_name;
        this.my_siblings = my_siblings

        my_siblings.push(obj_name);
    }
};
var my_obj_constructor = ANONYMOUS_VARIABLE();

Of course 'ANONYMOUS_VARIABLE' is just something I made up on the fly. Just to show you that is exactly what is happening above except that the anonymous variable is never mentioned because... It is anonymous.

Ok, back to what we were doing.

var my_obj_constructor = (function(){

    // This is inside this function's scope.
    var my_siblings = [];

    // This return value is what my_obj_constructor will contain.
    // This function is the actual constructor for the object.
    // Each object will run this constructor and this constructor
    // will always have a persistent my_siblings array that was
    // in its scope at the time the constructor was created.
    return function(obj_name) {
        // This isn't necessary, just for fluff.
        this.name = obj_name
        // We only need to save this off here so that once
        // the instance is created we have a way of accessing
        // the my_siblings variable.
        this.my_siblings = my_siblings

        // Now we push our name onto the my_siblings array.
        my_siblings.push(obj_name);
    }
})();

// Create each object that, on the last line of the constructor, pushes its name
// onto the my_siblings array.
var obj_1 = new my_obj_constructor('obj1');
var obj_2 = new my_obj_constructor('obj2');
var obj_3 = new my_obj_constructor('Shaflibble');

// Now we can call any of the objects and output their 'my_siblings' and
// see everyone's name.
console.log(obj_1.my_siblings); // Returns: ['obj1', 'obj2', 'Shaflibble']
console.log(obj_2.my_siblings); // Returns: ['obj1', 'obj2', 'Shaflibble']
console.log(obj_3.my_siblings); // Returns: ['obj1', 'obj2', 'Shaflibble']
// And just to show that they are unique objects.
console.log(obj_1.name); // Returns: 'obj1'
console.log(obj_2.name); // Returns: 'obj2'
console.log(obj_3.name); // Returns: 'Shaflibble'

One Last Example For The Road.

Not much in the way of explanations but I want to show why making a 'self' variable that points to an Object's 'this' is extremely handy to do for many reasons but specifically closures on creating callbacks like event handlers.

var thing_constructor = function(name) {
    var self          = this;
    self.name         = name;
    self.introduction = "Hello, I am " + self.name;

    this.click_handler = function() {
        $(this).html(self.introduction)
    };
};

var thing = new thing_constructor('Jabba The Slut');

var jQDiv = $('div');
jQDiv.click(thing.click_handler);

// Because of closures, 'self.introduction' inside the 'click_handler' function
// exists because 'self' was in click_handler's scope when the function was
// defined.

// Even more conveniently, 'this' became the clicked element so if we didn't have
// 'self' we wouldn't be able to do much of anything. With self, we have total access
// to our object from inside the handler even if the handler is passed along at
// a later point in the code.

Summary

Closures are an essential part of javascript. Just remember the following:

Variables that are in scope at the time of a function's declaration will always be available inside that function even if that function is called somewhere elsewhere entirely.

Closures are extremely handy when writing callbacks like event handlers. Simply store the functions to a variable while in the scope you want them to be in. Then all you have to do is pass that variable as the callback and you will always have everything you need in scope.

Hopefully this has been helpful.