如何使用闭包在Javascript for循环中创建事件侦听器?

时间:2015-12-23 05:15:47

标签: javascript for-loop closures addeventlistener

HTML

<span class="char" id="0">?</span>
<span class="char" id="1">!</span>
<span class="char" id="2">"</span>
<span class="char" id="3">/</span>
<span class="char" id="4">%</span>
<span class="char" id="5">$</span>
...

的JavaScript

var charElems = document.getElementsByClassName('char');

for (var i=0; i < charElems.length; i++) {

    charElems[i].addEventListener('mouseover',function() {

        (function(j) {mouseoverCheck(j);}(i));

    });

}

我有一堆(数百个)span元素,数字为ID(从0开始,递增1)。这个循环应该做的是为所有span元素(都有char类)创建鼠标悬停事件监听器。一旦被鼠标移除,它应该超出mouseoverCheck()函数并传入创建该事件监听器时的i。所以第203个事件监听器应该传入203。但事实并非如此。现在,它传递了我认为是循环完成之前的最后一个值i

我试图使用IIFE和闭包来确保每个事件监听器在创建时获得i的值,而不是调用函数时的值。显然,我没有正确地做到这一点,但我相当肯定关闭是我问题的关键。任何人都可以了解如何正确地做到这一点?我以为我理解了封闭,但显然我没有...

2 个答案:

答案 0 :(得分:3)

它不起作用,因为

charElems[i].addEventListener('mouseover',function() {

        (function(j) {mouseoverCheck(j);}(i));

    });

addEventListener()只是分配一个处理程序,并且当处理程序被调用时i将为6。

你应该从IIFE返回一个处理程序

var charElems = document.getElementsByClassName('char');

  for (var i=0; i < charElems.length; i++) {

      charElems[i].addEventListener('mouseover', (function(temp) {

        return function(){
             var j = temp;
             //mouseoverCheck(j);
             console.log(temp);
       }
    }(i)));
} 

这是一个小提琴:https://jsfiddle.net/qshnfv3q/

答案 1 :(得分:0)

var charElems = document.getElementsByClassName('char');

for (var i = 0; i < charElems.length; i++) {

    //close...
    //charElems[i].addEventListener('mouseover',function() {
    //    (function(j) {mouseoverCheck(j);}(i));
    //});

    //like this
    (function(el, x) {
        el.addEventListener("mouseover", function() {
            mouseoverCheck(x);
        });
    })(charElems[i], i)


}