2013-12-14 29 views
8

我有這樣的代碼:addEventListener,for(),索引。如何使用閉包?

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

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

該事件是聽了,但也有3項目和警報上的任何元素(它不尊重指數)的打印永諾3

Dosen't items[i]不應該作爲關閉工作嗎?

謝謝!

+0

的第三個參數['addEventListener' ](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener)是一個布爾值,指示事件偵聽器是否獲得捕獲優先級(例如,使其可取消);它沒有指定一個'this'值。 – apsillers

+0

還相關,[Javascript臭名昭着的循環問題?](http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem)。 –

回答

9

這是一個經典的關閉問題:你必須在結合時創建的約束,而不是「我」的變量,但其值的新功能:

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

感謝您的anser,這工作。只有使用匿名函數纔有可能嗎?只是好奇......謝謝! –

+0

不客氣。存儲在偵聽器中的函數是匿名的。你可能不想創建這個中間變量,只需在addEventListener中用值替換'listener'即可。但我認爲這樣更容易理解。 – GameAlchemist

+0

Javascript解釋器沒有進行優化,所以定義'function listener(index){return function(){...}; }'在循環外部,然後在循環內部有單個語句'items [i] .addEventListener('click',listener(i));''效率來自定義外部函數一次。如上所述,外部函數在循環的每次迭代中定義(並執行)。 –

7

不,第三個參數addEventListeneruseCapture之一。有關更多信息,請參閱MDN

但是你可以使用:

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

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

第一個創建的每個元素的新事件處理程序,因此它需要更多的內存。第二個重用同一事件偵聽器,但使用indexOf,所以它更慢。