Closures in Javascript

A Closure in its simplest term is an Inner Function (function within a function) that has access to its variables and the Outer Function’s variables. Closures (the inner function) will still have access to the outer function’s variables even when the outer function returns. So, we can store the inner function in a variable and execute it later in time and still have access to the outer function’s variables. Closure do not actually hold the outer function’s variables instead it holds the references. So, if the outer function’s variable’s values changes so will values for the Closure when it executes.

The following is an example where Closure is used to demonstrate using Properties in Javascript e.g. making use of Private variable, getter and setter as Closures:

function celebrityID() {
    var celebrityID = 999;
    return {
        getID: function () {
            return celebrityID;
        },
        setID: function (theNewID) {
            celebrityID = theNewID;
        }
    };
}

var mjID = celebrityID();//Returns the object inside
mjID.getID(); //999
mjID.setID(567); 
alert(mjID.getID()); //567

But the fact that outer function variables are stored as references in Closures also arises problems like in a for loop in Javascript with Closures depicted in the following code:

function celebrityIDCreator(theCelebrities) {
    var uniqueID = 100;
    for (i = 0; i < theCelebrities.length; i++) {
        theCelebrities[i].id = function () {
            return uniqueID + i;
        };
    }
    return theCelebrities;
}

var actionCelebs = [{
    name: "Stallone",
    id: 0
}, {
    name: "Cruise",
    id: 0
}, {
    name: "Willis",
    id: 0
}];

var createIdForActionCelebs = celebrityIDCreator(actionCelebs);
var stalloneID = createIdForActionCelebs[0];
alert(stalloneID.id());

So, what we are trying to do in above code is to pass in an array of objects to a function where its property will be modified and then we get to output the modified property. In the celebrityIDCreator() function we are running a for loop and assigning a function to the array of objects passed and then returning the modified array. According to the logic we will expect the output alerted to be 100 but it will appear to be 103. Because when the function in id is invoked it will execute exactly then and by then the for loop had executed and i had been modified and incremented to 3 so the returning value from the Closure would be 103.

As a side note, Javascript is not Block Scope so the i counter initialized can be accessed from anywhere within the function and that is why it is Function Scoped instead.

So, what can we do to achieve what we want to do above correctly? One option is to execute the anonymous function here (Closure) then and there inside the for loop as the counter progresses and return only the modified id instead of assigning a function which needs to be executed thus, not repeating the error again. To do that we code the following:

function celebrityIDCreator(theCelebrities) {
    var uniqueID = 100;
    for (i = 0; i < theCelebrities.length; i++) {
        theCelebrities[i].id = function () {
            return uniqueID + i;
        }(); //'()' will execute the function then and there
    }
    return theCelebrities;
}

var actionCelebs = [{
    name: "Stallone",
    id: 0
}, {
    name: "Cruise",
    id: 0
}, {
    name: "Willis",
    id: 0
}];

var createIdForActionCelebs = celebrityIDCreator(actionCelebs);

var stalloneID = createIdForActionCelebs[0];
alert(stalloneID.id); // 100

var cruiseID = createIdForActionCelebs[1];
alert(cruiseID.id); // 101

var willisID = createIdForActionCelebs[2];
alert(willisID.id); // 102

I scoured the net before understanding Closure. So, do not hate me if you have seen something here before :P