2013-12-14 20 views
8

mam ten kod:addEventListener, for(), index. jak korzystać z zamknięcia?

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

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

gdy zdarzenie jest słuchany, ale istnieją 3 przedmioty i nieczysto zawsze dobrze wydrukować 3 na każdy z elementów (nie szanować indeks),

Dosen't items[i] nie powinien wykonywać pracy jako zamknięcia?

dziękuję!

+0

Trzeci argument [ 'addEventListener' ] (https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener) jest wartością logiczną, która wskazuje, czy detektor zdarzeń uzyska priorytet przechwytywania (np. w celu umożliwienia jego anulowania); nie określa wartości "this". – apsillers

+0

Związany z tym problem [niesławny problem z pętlą JavaScript?] (Http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem). –

Odpowiedz

9

To klasyczny problem zamykający: należy utworzyć nową funkcję związaną, a nie do zmiennej „ja”, ale do jego wartości w czasie wiązania:

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

Dzięki za anser, to działa. Czy jest to możliwe tylko za pomocą funkcji anonimowych? tylko ciekawy .. dzięki! –

+0

Nie ma za co. Funkcja przechowywana w odbiorniku jest anonimowa. Możesz nie chcieć utworzyć tego pośredniego var i po prostu zastąpić, w addEventListener, "listener" przez jego wartość. Jednak myślę, że jest to łatwiejsze do zrozumienia w ten sposób. – GameAlchemist

+0

Tłumacze JavaScript nie optymalizują się, więc bardziej efektywne jest zdefiniowanie funkcji detektor (index) {funkcja return() {...}; } 'poza pętlą, następnie pojedyncza instrukcja' items [i] .addEventListener ("kliknij", słuchacz (i)); 'wewnątrz pętli. Efektywność wynika z jednorazowego zdefiniowania funkcji zewnętrznej. Jak napisano powyżej, zewnętrzna funkcja jest definiowana (i wykonywana) przy każdej iteracji pętli. –

7

Nie, trzecim argumentem jest addEventListener. Aby uzyskać więcej informacji, patrz MDN.

Ale można użyć:

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

lub

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

Pierwszy z nich tworzy nowy obsługi zdarzeń dla każdego elementu, więc potrzebuje więcej pamięci. Drugi używa tego samego detektora zdarzeń, ale używa indexOf, więc jest wolniejszy.