I've rewritten a short article explaining closures in JavaScript.
It's
at:
http://www.martinrinehart.com/articles/javascript-closures.html
A big Thank You to PointedEars and Jorge for helping me get closer to
the truth.
Comments:
In the example:
function outer() {
// args here
// code here
function inner() {
// more args and code
}
} // end of outer()
the "args here" comment seems slightly misleading. Arguments goes
between the parentheses. Maybe use:
function outer(/* arguments here *) {
instead.
The sentence "A closure is a bundle of data and code that manipulates
that data" is still indistinguishable from the description of an
Object.
A closure is a piece of code together with a binding of values to the
free variables of that code.
A free variable is one that occur in the code, but is not declared
there.
The next sentence, "In JavaScript it's a function with data that's
unavailable, except to the function." is closer, but also wrong.
The data, and even the bindings, might be available to other code too.
Example:
function pair(a,b) {
return {setFst : function(x){a=x;},
setSnd : function(x){b=x;},
sum : function() { return a+b; }};
}
var p = pair(2,4);
var s = p.sum; // s holds a clousre, but its data and bindings
// are available through, e.g., pair.setFst:
alert(s());
p.setFst(38);
alert(s());
So, what you describe as "What is a Closure?" isn't correct. It is
one use of a closure: to create functions with shared private variables.
It seems this use of closures is the focus of your page, but it should
really be named "private variables in Javascript, using closures" instead.
Closures are MUCH more than just that, e.g.:
function curry(f) {
return function(a) {
return function (b) {
return f(a,b);
}
}
}
function sum(a,b) { return a+b;};
var csum = curry(sum);
var inc = csum(1);
var addFive = csum(5);
alert([inc(41),addFive(37)]);
or it can be used to express something complicated in a simpler way:
function map(arr,f) {
var res = [];
for(var i = 0; i < arr.length; i++) {
res
= f(arr);
}
return res;
}
function cross(arr1,arr2) {
return map(arr1, function(x1) {
return map(arr2, function(x2) { return [x1,x2]; });
});
}
var pair_matrix = cross([1,2,3],[4,5,6]);
// pair_matrix ==
// [[[1,4],[1,5],[1,6]],
// [[2,4],[2,5],[2,6]],
// [[3,4],[3,5],[3,6]]]
(try doing it shorter using nested loops
And to prettify it:
alert(map(pair_matrix, function(a1) {
return map(a1, function(a2) {
return "(" + a2[0] + "," + a2[1] +")";
}).join(",");
}).join("\n"));
To put it bluntly: Closures allow you to write functional programs.
If only we had tail-calls, it would be perfect
/L