In writing my programs with JavaScript, I never really completely understood the closure idea. I still think I don’t, but here is how I will try to explain it to myself. The idea and code used is from one of the Youtube videos of Douglas Crockfords ‘the good parts’.
We can start with a simple example. We want to turn digits into strings, something like this:
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'ate', 'nine' ];
function digit_name(n) {
return names[n];
}
digit_name(4); // returns ‘four’.
This code will run ok, but it has a problem: the names array is global. Any other JavaScript on the page can break our code by writing over our “names” variable.
So we could do this:
function digit_name(n) {
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'ate', 'nine' ]; // this is now private to our function
return names[n];
}
digit_name(4); // returns ‘four’.
This code is better – we have a self-sufficient function, without polluting global namespace. But now, every time we call the function, we re-initialize our names array.
How to avoid it? Here is an example:
var digit_name = function () {
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'ate', 'nine' ];
return function (n) {
return names[n];
}
}
This is now much better. What happens on executing? First, a private array is initialized and stored to memory. Then we return a function that will look up our names array and find the result.
Wait, what?
Well – the array is initialized and left in memory. And each time somebody calls our returned function from digit_name(n), that returned function will look up into the now-enclosured (in lack of better term) array.
It means that our later function call doesn’t execute digit_name – it only executes the anonymous function we returned. And that function has access to our private variable.
So the anonymous inner function will execute when needed, but our array is only initialized once (and held in a closure).
So the module pattern for creating stuff in closures should be something like this:
var singleton = function () {
var privateVariable; // only created once
function privateFunction() { // only created once
…
};
return {
methodOne: function (param) { // this is exported out once.
// so when we call singleton.methodOne(param)
// later, the private stuff above is already there and
// within closure
},
methodTwo: function(a, b) { // another public method
….
},
publicInt: 10
};
}
// now calling and instantiating the object will have the object being created, private vars and methods left there, and public stuff exposed to us.
I think I got it right, hopefully this will help me (and possibly others) in the future.