循环中的addEventHandler()具有意外结果

时间:2011-06-11 19:02:53

标签: javascript javascript-events

我不知道该找什么,所以我在这个主题上找不到任何先前的问题,谷歌也没有多少帮助。

(function() {
    var element = function(str) {
        return document.getElementById(str);
        },

        parent = document.getElementsByTagName('ul')[0].getElementsByTagName('li'),
        len = parent.length,

        slides = slides || [];

    for (var i=0; i<len; i++) {
        var link = parent[i].getElementsByTagName('a')[0],
            slide = element(parent[i].getElementsByTagName('a')[0].getAttribute('href').substr(1));


        if (addEventListener) {
            link.addEventListener('click', function(event){
                event.preventDefault();
                alert(slide.getAttribute('id'));
            });
        } else if (attachEvent) {

        }
    }

})();

因此,在上面的代码中,在for循环中,我将一个事件附加到所有链接(其中五个),这些链接应该提醒他们指向的幻灯片的ID(仅用于调试目的),但是都显示最后一张幻灯片的ID。我还创建了一个jsFiddle供您查看...动作。

我假设我搞砸了一些相对简单的东西,我只是想不出来。

2 个答案:

答案 0 :(得分:7)

javascript中的变量是函数范围,即使在块中声明它们也是如此。这个循环在变量循环周围创建一个闭包,但是在每次迭代时都会重新分配循环。循环完成时,所有闭包都指向数组中的最后一个元素。

要解决此问题,请以不同方式调整变量的范围:

(function() {
    var element = function(str) {
        return document.getElementById(str);
        },

        parent = document.getElementsByTagName('ul')[0].getElementsByTagName('li'),
        len = parent.length;

    for (var i=0; i<len; i++) {
        var link = parent[i].getElementsByTagName('a')[0],
            slide = element(parent[i].getElementsByTagName('a')[0].getAttribute('href').substr(1));


        if (addEventListener) {
            link.addEventListener('click', (function(slide){
                return function(event) {
                    event.preventDefault();
                    alert(slide.getAttribute('id'))
                }
            })(slide));
        } else if (attachEvent) {

        }
    }

})();

答案 1 :(得分:3)

之前我遇到过这个bug,它与slide的绑定有关,这很难解释。这是一个修复。

link.addEventListener('click',
    (function(x) {
       return function(event){
                event.preventDefault();
                alert(x.getAttribute('id'));
              }
     })(slide));