Joost said:
David said:
Here's some JavaScript that does not do what I would like
it to do:
var x = new Object();
var y = new Object();
var j;
for (j=0; j<5; j++) {
x['f'+j] = function () { print(j); };
}
for (j=0; j<5; j++) {
var jj = 0+j;
y['f'+j] = function () { print(jj); };
}
x.f0(); // prints 5
y.f0(); // prints 4
You're closing over global variables. You want to close over
newly instantiated variables instead. Something like this:
I suspect that taking of 'closing over variables' is directly
responsible for much of the confusion in the minds of people new to
closures. The closure relationship is between functions and the
(scope/execution context) environment in which they are created, and
understanding the implications of that would make it obvious that
function objects created in the same environment would share their
association with that single environment.
for (var j=0; j<5; j++) {
x['f'+j] = (function(i) { return function () { print(i); } })(j);
}
or if you prefer:
for (var j=0; j<5; j++) {
x['f'+j] = (function() {
var i = j;
return function () { print(i);
} })();
}
<snip>
There are questions of efficiency with regard to the number of function
objects created here. The evaluation of any function expression is
likely to result in the creation of a new function object (there is no
evidence that any implementations take advantage of the specifications
provision for 'joined' objects where function creation is concerned). So
above each iteration of the loop results in the creation of two function
objects, where the outer of those two function objects does not need to
have multiple instances. And finding such a construct inside a function
body means that the number of function objects created is -
(callsToTheFunction * loopIterations * 2) -.
It would be possible to either declare the equivalent of the outer of
the two functions as a declared inner function of the function that
contained the loop (were the odds were good that the loop would be
executed (and at least one iteration was likely) or conditional create
that function with a function expression (where there was a reasonable
possibility of the loop body not always being executed and so that
function not being needed. That would reduce the number of function
objects created to - (callsToTheFunction * (loopIterations + 1)) -.
It would also be possible to move the outer of the two functions outside
of the function that contained the loop, making the total number of
function objects created - (1 + (callsToTheFunction * loopIterations)) -
which might be a good idea when - callsToTheFunction - was expected to
be large.
One of the things that I observe in, and don't like about, the usage
patters that follow from design decisions in many current 'popular'
libraries is the excessive number of function (and other) objects
created for no real reason; the failure to appreciate that many of these
things could be re-used (trading (long-term) memory use for execution
speed (because if you are continually re-creating and then abandoning
objects the short term memory use will be high-ish anyway, as garbage
collection in browser environments has been observed to be relatively
low priority)).
Richard.