2009-06-24 4 views
6

Sto lavorando su una pagina web che utilizza dojo e ha un numero (6 nel mio caso di test, ma variabile in generale) di widget di progetto su di esso. Sto invocando dojo.addOnLoad (init), e nella mia funzione init() Ho queste righe:Perché non riesco a far circolare un loop in Javascript?

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);}); 

e cambiare gli eventi per il mio progetto un widget per richiamare correttamente la funzione makeMatch. Ma se li sostituisco con un ciclo:

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

stesso makeMatch(), lo stesso init) invocazione, (lo stesso tutto il resto - solo a rotazione le mie chiamate su in un ciclo - la funzione makeMatch non viene mai chiamato; gli oggetti non sono cablati.

Cosa sta succedendo e come lo risolvo? Ho provato a usare dojo.query, ma il suo comportamento è lo stesso del caso ciclo for.

risposta

11

questo è un problema comune quando si tratta di chiusure. prova questo:

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

Eccellente; grazie; questo funziona perfettamente. Penso che ci vorrà molto tempo per capire chiusure. –

+6

prendi un libro chiamato "javascript the good parts" e capirai chiusure, tra le altre cose. – mkoryak

+0

Grazie; Lo cercherò. –

8

I è una variabile locale all'interno del ciclo for. Quando la funzione onChange viene chiamata, tutte le 6 funzioni hanno un riferimento di i, che è 6.

È lo stesso problema #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(); 
} 

che stampa tutte 10 del