Question

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.

Was it helpful?

Solution

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(); }); 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top