如何确保addEventListener不会忽略for循环中i var的迭代?

时间:2013-05-31 13:25:34

标签: javascript

我正在制作一个会生成大量按钮的用户脚本,而且我似乎无法为它们提供所有独特的功能。

我已经尝试过了

 downArrow.onclick = function (){downVote(id, username)};<br>

 downArrow.onclick = "downVote(\"" + id + "\", \"" + username + "\")";

但他们不起作用。然后我在某处读到只有以下工作:

 downArrow.addEventListener('click', downVote(id, username), false);

这会导致所有按钮仅下调迭代的最后一个ID和用户名。

我希望他们都拥有独特的onclick功能。

整个循环:

var targetPosts = document.getElementsByClassName("thing message");
for (var i=0;i<targetPosts.length;i++) 
    {
    try
      {
        id = targetPosts[i].getAttribute("data-fullname");
        username = targetPosts[i].childNodes[4].childNodes[1].childNodes[0].childNodes[1].childNodes[1].childNodes[0].innerHTML;

        var upArrow=document.createElement("DIV");
        upArrow.className = "arrowUp";
        upArrow.id = id + "up";
        upArrow.addEventListener('click', function(){ upVote(id, username)} , false);

        var downArrow=document.createElement("DIV");
        downArrow.className = "arrowDown";
        downArrow.id = id + "down";
        downArrow.addEventListener('click', function(){ downVote(id, username)} , false

      targetPosts[i].childNodes[3].appendChild(upArrow);
      targetPosts[i].childNodes[3].appendChild(downArrow);
      }
    catch(err){}
    }

3 个答案:

答案 0 :(得分:4)

bind是针对这种情况而发明的:

 upArrow.addEventListener('click', upVote.bind(upArrow, id, username), false);

应该做的。

答案 1 :(得分:3)

由于JavaScript没有块范围(将附带ES6),请尝试以下操作:

downArrow.addEventListener('click', function(uid, uname) {
    return function() {
        downVote(uid, uname);
    };
}(id, username), false);

当调用匿名函数(立即发生)时,您捕获当前状态idusername并在调用内部函数时使用它(当用户单击按钮时发生)。

在ES6中,您可以使用let id = ...来定义具有块范围的变量,并且您发布的代码应该可以正常工作。

答案 2 :(得分:3)

我不确定你是怎么做的(最好显示循环代码),但一般来说,在循环中创建函数不是很安全,因为你可以错误地引用变量在里面改变一个循环,所以最后你将获得所有使用相同ID的函数。解决方案是使用一些辅助函数:

var bindClick = function (element, id, username) {
        element.addEventListener('click', function () {
            downVote(id, username);
        }, false);
    },
    i, mybutton;
for (i = 0 ; i < amountOfUsers ; ++i) {
    mybutton = document.getElementById('downvote-handle-' + i);
    bindClick(mybutton, i, usernames[i]);
}

这种方式i值被复制(按值传递)并且是安全的。

它也可以用匿名函数完成,结果将是相同的(但恕我直言不太可读):

for (i = 0 ; i < amountOfUsers ; ++i) {
    mybutton = document.getElementById('downvote-handle-' + i);
    (function (element, id, username) {
        element.addEventListener('click', function () {
            downVote(id, username);
        }, false);
    }(mybutton, i, userames[i])); 
}