Can someone explain to me (clearly and concisely) why this code works the way it does? I come from a strongly typed background in Java (6 and 7) where closures don't exist and do not function the way they do in javascript. I think the concepts related to this question are: closures and scope chain.
Here's the example:
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = function() { console.log(i); }
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });
The above example logs 9 (10 times), but the expectation and my own intuition was thinking it would log 0-9.
Why does this work the way it does in Javascript? Closures are very powerful, but I'm trying to grasp the concept once and for good! A slightly modified example produces the right output, but why?
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = (function(index) { console.log(index); })(i);
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });
Closures aren't unique to Javascript, but I want to see why they are powerful in the context of when javascript is actaully written to interface with the browser/dom.
Does anyone have good, practical examples of how we can apply the closure technique when interfacing with the browser/dom?
Thanks.
In the examples you have, it is very simple.
In your first example, there is only one variable i
and everything references that single value. So.. it prints the number 9
ten times. Each function captured a shared value of i
that changes.
In the second example you are using a closure. Each function has a private variable called index
which receives -- and here is the important part -- a copy of the value i
.
So, you get 0
through 9
because there are ten functions, each one with a private index
variable and each of those index
variables get a snapshot of i
as it existed at the time.
This, longer form of a closure, may help:
function myFactory(index) {
return function() {
console.log(index);
}
}
var myfuncs = function() {
var funcs = []
var i;
for (i = 0; i < 10; i++) {
funcs[i] = myFactory(i);
}
return funcs;
}
var allfuncs = myfuncs();
allfuncs.forEach(function(fn) { fn(); });