2009-06-01 20 views
5

Sto leggendo un articolo (JavaScript Closures for Dummies) e uno degli esempi è il seguente.Come si fa riferimento alle variabili locali nelle chiusure?

function buildList(list) { 
    var result = []; 
    for (var i = 0; i < list.length; i++) { 
    var item = 'item' + list[i]; 
    result.push(function() {alert(item + ' ' + list[i])}); 
    } 
    return result; 
} 

function testList() { 
    var fnlist = buildList([1,2,3]); 
    // using j only to help prevent confusion - could use i 
    for (var j = 0; j < fnlist.length; j++) { 
    fnlist[j](); 
    } 
} 

testList(); 

Quando viene chiamata la lista di prova, una casella di avviso che dice "elemento3 non definito". L'articolo ha questa spiegazione:

Quando le funzioni anonime sono chiamate sulla linea fnlist[j](); tutti usano la stessa chiusura singola, e usano il valore corrente per i e articolo entro quella di chiusura (in cui i ha un valore di 3 perché il ciclo è stato completato, e l'articolo ha un valore di 'item3').

Perché l'articolo ha un valore di "articolo3"? Il ciclo for non termina quando divento 3? Se finisce, l'elemento non dovrebbe essere ancora 'item2'? O la voce variabile viene creata di nuovo quando testList chiama le funzioni?

+0

è un bug che causa più testo del previsto? – CookieOfFortune

risposta

4

Sei chiuso ...

Perché articolo ha un valore di 'item3'? Il ciclo for non termina quando divento 3?

Sì.

Se termina, l'articolo non deve essere ancora "elemento2"?

No. Questo esempio è un po 'complicato. Durante l'ultima iterazione del ciclo, i è 2, ma fa riferimento al terzo elemento della list matrice, che è 3. In altre parole, item == 'item' + list[2] == 'item3'

O è l'elemento variabile creata nuovo quando TestList chiama le funzioni ?

No, avevi quasi ragione la prima volta. Penso che appena perso che item[2] ha il valore di 3.

+0

Wow è così semplice. Come mi sono perso? L'intera faccenda del conteggio alla rovescia è sempre a disagio. Grazie! – hekevintran

+0

Se quello era l'unico ostacolo per te a capire la chiusura di javascript, datti una pacca sulla spalla! Penso che quell'esempio sia stato inutilmente complicato. – Triptych

0

Il ciclo termina quando i diventa 3, ma la variabile "voce" memorizzata nella chiusura, e visualizzato da avviso, è impostato per

var item = 'item' + list[i]; 

il testo 'elemento' + il valore alla lista [2]. Il terzo elemento dell'elenco è 3, quindi il testo è item3

2

La variabile list viene memorizzata in chiusura come dici tu.

In realtà è possibile accedere alla variabile list, ma si sta tentando di accedere a list[3]. Dopo tutto, anche la variabile i viene archiviata come chiusura e il suo valore è 3 quando viene chiamata la funzione console.log.

4

Il ciclo for all'interno buildList completa prima di effettuare le seguenti operazioni:

for (var j = 0; j < fnlist.length; j++) { 
    fnlist[j](); 
} 

... quindi, da quel momento (quando si chiama ciascuna funzione), la variabile item sarà tutto ciò che era ultima ad esso assegnata (vale a dire"item3") e i sarà 3 (a seguito dell'ultima operazione i++) e list[3] è undefined.

È tutto a che fare con il completamento del ciclo prima di chiamare la funzione closure. Per evitare questo, si potrebbe creare una nuova chiusura, in questo modo:

function buildList(list) { 
    var result = []; 
    for (var i = 0; i < list.length; i++) { 
    var item = 'item' + list[i]; 
    result.push(
     (function(item, i){ 
      // Now we have our own "local" copies of `item` and `i` 
      return function() { 
       console.log(item + ' ' + list[i]) 
      }; 
     })(item, i) 
    ); 
    } 
    return result; 
} 
+0

@ J-P, Grazie per l'ottima risposta. Ora capisco perché non è stato definito, ma posso chiederti perché sei un esempio. Perché ora c'è una nuova chiusura creata per ognuna delle funzioni ora memorizzate in fnlist? – screenm0nkey

+0

Quella funzione dichiarata e chiamata all'interno della chiamata a "result.push" crea la propria chiusura. – Pointy

+0

@Pointy, perché crea la propria chiusura? Perché è una funzione anonima? – screenm0nkey

2

Credo che il punto vi manca è che list[i] è underfined perché i è 3, e list è definita solo per 0..2.

Problemi correlati