2009-11-04 16 views
23

considerare tali ciclo:JavaScript variabile vincolante e ciclo

for(var it = 0; it < 2; it++) 
{ 
    setTimeout(function() { 
     alert(it); 
    }, 1); 
} 

L'output è:

=> 2 
=> 2 

vorrei che fosse: 0, 1. vedo due modi per risolvere il problema:

Soluzione # 1.

Questo sulla base del fatto che siamo in grado di trasmettere i dati a setTimeout.

for(var it = 0; it < 2; it++) 
{ 
    setTimeout(function(data) { 
     alert(data); 
    }, 1, it); 
} 

Soluzione # 2.

function foo(data) 
{ 
    setTimeout(function() { 
     alert(data); 
    }, 1); 
} 

for(var it = 0; it < 2; it++) 
{ 
    foo(it); 
} 

Ci sono altre alternative?

risposta

42

Non proprio qualcosa di più di due modi che si è proposto, ma qui è un'altra

for(var it = 0; it < 2; it++) 
{ 
    (function() { 
     var m = it; 
     setTimeout(function() { 
      alert(m); 
     }, 1); 
    })(); 
} 

In sostanza, è necessario acquisire il valore della variabile in una chiusura. Questo metodo utilizza una funzione anonima richiamata immediatamente per acquisire il valore della variabile esterna it in una variabile locale m.

Ecco un Working Demo con cui giocare. aggiungere /modificare all'URL per vedere il codice

+4

+1. Tuttavia, è possibile modificarlo leggermente modificando la firma del metodo su: 'function (m) {/ * code * /}) (it);' – Alan

+0

+1, ma qualcuno può spiegarmi perché questo funziona ?! –

+1

@digorydoo La funzione dichiarata nel ciclo è racchiusa tra parentesi seguita da un insieme di parentesi che agiscono per richiamare immediatamente la funzione. Dato che le variabili sono circoscritte alla funzione in cui sono dichiarate (o all'ambito globale se non dichiarate all'interno di una funzione), il valore di 'it' in ogni iterazione è assegnato alla variabile' m' che viene portata alla funzione che viene eseguita subito. –

1

Simile alla soluzione di cui sopra ma auto invocazione all'interno della funzione setTimeout

for(var it = 0; it < 2; it++) 
{ 
    setTimeout(function(cur) { 
     return function(){ 
      alert(cur); 
     }; 
    }(it), 1); 
} 
7

Con la parola chiave let è possibile aggirare il problema completamente:

for(let it = 0; it < 2; it++) 
{ 
    setTimeout(function() { 
     alert(it); 
    }, 1); 
} 
+0

ma non c'è una parola chiave denominata 'let' in javascript è in dattiloscritto penso –

1

Simile alle altre soluzioni, ma a mio parere più pulito:

for (var it = 0; it < 2; it++) { 
    // Capture the value of "it" for closure use 
    (function(it) { 
    setTimeout(function() { 
     alert(it); 
    }, 1); 
    // End variable captured code 
    })(it) 
} 

Ciò mantiene lo stesso nome di variabile per l'acquisizione e lo esegue per l'intero ciclo, separandolo dalla logica dell'impostazione di timeout. Se vuoi aggiungere più logica all'interno del blocco, puoi farlo banalmente.

L'unica cosa che non mi piace della soluzione è la ripetizione di "esso" alla fine.

Problemi correlati