views:

335

answers:

2

I am working on a web page that uses dojo and has a number (6 in my test case, but variable in general) of project widgets on it. I'm invoking dojo.addOnLoad(init), and in my init() function I have these lines:

dojo.connect(dijit.byId("project" + 0).InputNode, "onChange",  function() {makeMatch(0);});
dojo.connect(dijit.byId("project" + 1).InputNode, "onChange",  function() {makeMatch(1);});
dojo.connect(dijit.byId("project" + 2).InputNode, "onChange",  function() {makeMatch(2);});
dojo.connect(dijit.byId("project" + 3).InputNode, "onChange",  function() {makeMatch(3);});
dojo.connect(dijit.byId("project" + 4).InputNode, "onChange",  function() {makeMatch(4);});
dojo.connect(dijit.byId("project" + 5).InputNode, "onChange",  function() {makeMatch(5);});

and change events for my project widgets properly invoke the makeMatch function. But if I replace them with a loop:

for (var i = 0; i < 6; i++) 
    dojo.connect(dijit.byId("project" + i).InputNode, "onChange",  function() {makeMatch(i);});

same makeMatch() function, same init() invocation, same everything else - just rolling my calls up into a loop - the makeMatch function is never called; the objects are not wired.

What's going on, and how do I fix it? I've tried using dojo.query, but its behavior is the same as the for loop case.

+6  A: 

i is a local variable inside the for loop. When the onChange function is called, all 6 functions have a reference to i, which is 6.

It's the same problem as #4 on Jon Skeet's C# Brainteaser's page

List<Printer> printers = new List<Printer>();
for (int i=0; i < 10; i++)
{
    printers.Add(delegate { Console.WriteLine(i); });
}

foreach (Printer printer in printers)
{
    printer();
}

which prints all 10's

Tom Ritter
+10  A: 

this is a common problem when dealing with closures. try this:

for (var i = 0; i < 6; i++) {
    (function(i){
      dojo.connect(dijit.byId("project" + i).InputNode, "onChange",  function()   {makeMatch(i);});
    }(i));
}
mkoryak
Excellent; thank you; this works perfectly. I think it will take me a long time to understand closures.
Carl Manaster
get a book called "javascript the good parts" and you will understand closures, amongst other things.
mkoryak
Thanks; I'll look for it.
Carl Manaster