带有 addEventListener 的循环对于 function() 不是动态的

Loop with addEventListener is not dynamic for function()

我想制作一个非常简单的 for 循环来为每个按钮调用一个具有不同参数的函数。但是,当我 运行 调用并单击按钮时,eventListener 函数 saveList(listIdx) 仅 returns 函数 saveList("5")。请看看我的问题和故障排除。

    for (var listIdx = 0; listIdx < count; listIdx++ ) {
            console.log("setting the variable" + "myButton" + listIdx );

            document.getElementById("myButton" + listIdx).addEventListener("click", function() { saveList(listIdx); 
            });
    }

尝试 1:向 function() 调用添加参数

    for (var listIdx = 0; listIdx < count; listIdx++ ) {
            console.log("setting the variable" + "myButton" + listIdx );

            document.getElementById("myButton" + listIdx).addEventListener("click", function(listIdx) { saveList(listIdx); 
            });
    }

尝试 2:元素上的包装器

    for (var listIdx = 0; listIdx < count; listIdx++ ) {
            console.log("setting the variable" + "myButton" + listIdx );

            document.getElementById("myButton" + listIdx).addEventListener("click", function(_listIdx) { saveList(_listIdx); 
            });
    }

问题是函数在稍后的时间点被调用——在 for 循环完成之后。主体中包含的变量已经在 for 循环的最后一次迭代中被更新。这就是您所看到的。

解决方法是以某种方式将变量推送到内部函数。

function makeListSaver(index) {
    /* return a brand new function that has captured the index when this function 
       was invoked
    */
    return function() { 
        saveList(index);
    }
}

然后做,

document.getElementById("myButton" + listIdx).addEventListener("click", makeListSaver(listIdx))

或者简单地说,

document.getElementById("myButton" + listIdx).addEventListener("click", (function(index){
   return function() { saveList(index); }
})(listIdx));

您需要稍微了解一下闭包及其工作原理。

问题出在循环上。

这里是如何在 for 循环中设置 addEventListener 的简单示例。

http://jsbin.com/kavowucimi/1/

它是如何工作的:

  • 页面加载时
  • 查找具有 class 对象的所有元素。
  • 为每个元素添加一个事件监听器 click。
  • 当用户单击时,提醒所选元素的 ID。

<script>
    window.app = {
        start: function(){
            var elms = document.querySelectorAll('.obj');

            for (var i = 0; i < elms.length; i++ ) {
                var t = elms[i];
                var elm = document.getElementById(t.id);
                elm.addEventListener('click', function(item){
                    alert(item.currentTarget.id);
                });
            }
        }
    };

    </script>

<body onload="window.app.start();">
<div id=1 class="obj">1</div>
<div id=2 class="obj">2</div>
<div id=3 class="obj">3</div>

你可以这样做...

for (var listIdx = 0; listIdx < count; listIdx++ ) {
           applyEvent(listIdx);
    }

function applyEvent(listIdx)
{   
        document.getElementById("1" + listIdx).addEventListener("click", function({                
              saveList(listIdx); 
        });
}

工作Fiddle