2013-12-14 15 views
8

ho questo codice:addEventListener, per(), indice. come usare la chiusura?

var items = this.llistat.getElementsByTagName('a'); 

for(var i = 0; i < items.length; i++){  
    items[i].addEventListener('click', function(event) { 
    alert(i); 
    }, items[i]); 
} 

in cui l'evento è in ascolto, ma ci sono 3 oggetti e l'avviso allways stampare 3 su uno qualsiasi degli elementi (che non rispetta l'indice),

Dosen't items[i] non dovrebbe fare il lavoro come chiusura?

grazie!

+0

Il terzo argomento su [ 'addEventListener' ] (https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener) è un valore booleano che indica se il listener di eventi ottiene la priorità di acquisizione (ad esempio, per renderlo cancellabile); non specifica un valore 'this'. – apsillers

+0

Anche correlati, [Javascript infamous Loop problem?] (Http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem). –

risposta

9

questo è un problema di chiusura classica: è necessario creare una nuova funzione legata, non alla variabile 'i', ma per il suo valore al momento della rilegatura:

var items = this.llistat.getElementsByTagName('a'); 

for(var i = 0; i < items.length; i++) { 
     items[i].addEventListener('click', listener.bind(null, i)); 
} 

function listener(index) { 
     alert(index); 
} 
+0

Grazie per il tuo anser, questo funziona. È possibile utilizzare solo funzioni anonime? solo curioso .. grazie! –

+0

Prego. La funzione che è memorizzata all'interno del listener è anonima. Potresti non voler creare questa variabile intermedia e sostituire semplicemente, all'interno di addEventListener, 'listener' con il suo valore. Eppure penso che sia più facilmente comprensibile in questo modo. – GameAlchemist

+0

Gli interpreti JavaScript non ottimizzano quindi è più efficiente definire 'function listener (index) {return function() {...}; } 'outside the loop quindi hanno gli elementi' istruzione singola [i] .addEventListener ('click', listener (i)); 'all'interno del ciclo. L'efficienza deriva dal definire una volta la funzione esterna. Come scritto sopra, la funzione esterna viene definita (ed eseguita) ad ogni iterazione del ciclo. –

7

No, il terzo argomento di addEventListener è uno useCapture. Vedere MDN per ulteriori informazioni.

Ma è possibile utilizzare:

for(var i = 0; i < items.length; i++){ 
    (function(i){ 
     items[i].addEventListener('click', function(event) { 
      alert(i); 
     }, false); 
    })(i); 
} 

o

var handler = function(event) { 
    var i = items.indexOf(this); 
    alert(i); 
}; 
for(var i = 0; i < items.length; i++){ 
    items[i].addEventListener('click', handler, false); 
} 

La prima si crea un nuovo gestore di eventi per ogni elemento, quindi ha bisogno di più memoria. Il secondo riutilizza lo stesso listener di eventi, ma usa indexOf, quindi è più lento.