javascript – 使用for循环和传递值的addEventListener

参见英文答案 > JavaScript closure inside loops – simple practical example                                    43个
我正在尝试使用for循环向多个对象添加事件侦听器,但最终会使用针对同一对象的所有侦听器 – >最后一个.

如果我通过为每个实例定义boxa和boxb来手动添加侦听器,它就可以工作.我想这就是addEvent for-loop,它不像我希望的那样工作.也许我完全使用了错误的方法.

使用4个类=“容器”的示例
容器4上的触发按照预期的方式工作.
触发容器1,2,3触发容器4上的事件,但仅在触发器已被激活时触发.

// Function to run on click:
function makeItHappen(elem, elem2) {
  var el = document.getElementById(elem);
  el.style.backgroundColor = "red";
  var el2 = document.getElementById(elem2);
  el2.style.backgroundColor = "blue";
}

// Autoloading function to add the listeners:
var elem = document.getElementsByClassName("triggerClass");

for (var i = 0; i < elem.length; i += 2) {
  var k = i + 1;
  var boxa = elem[i].parentNode.id;
  var boxb = elem[k].parentNode.id;

  elem[i].addEventListener("click", function() {
    makeItHappen(boxa, boxb);
  }, false);
  elem[k].addEventListener("click", function() {
    makeItHappen(boxb, boxa);
  }, false);
}
<div class="container">
  <div class="one" id="box1">
    <p class="triggerClass">some text</p>
  </div>
  <div class="two" id="box2">
    <p class="triggerClass">some text</p>
  </div>
</div>

<div class="container">
  <div class="one" id="box3">
    <p class="triggerClass">some text</p>
  </div>
  <div class="two" id="box4">
    <p class="triggerClass">some text</p>
  </div>
</div>

解决方法:

瓶盖! :d

此固定代码按预期工作:

for (var i = 0; i < elem.length; i += 2) {
    (function () {
        var k = i + 1;
        var boxa = elem[i].parentNode.id;
        var boxb = elem[k].parentNode.id;

        elem[i].addEventListener("click", function() { makeItHappen(boxa,boxb); }, false);
        elem[k].addEventListener("click", function() { makeItHappen(boxb,boxa); }, false);
    }()); // immediate invocation
}

为什么要修复它?

for(var i=0; i < elem.length; i+=2){
    var k = i + 1;
    var boxa = elem[i].parentNode.id;
    var boxb = elem[k].parentNode.id;

    elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false);
    elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false);
}

实际上是非严格的JavaScript.它的解释如下:

var i, k, boxa, boxb;
for(i=0; i < elem.length; i+=2){
    k = i + 1;
    boxa = elem[i].parentNode.id;
    boxb = elem[k].parentNode.id;

    elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false);
    elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false);
}

由于variable hoisting,var声明被移动到范围的顶部.由于JavaScript没有块范围(for,if,while等),因此它们被移动到函数的顶部.更新:从ES6开始,您可以使用let获取块范围变量.

当代码运行时会发生以下情况:在for循环中添加单击回调并指定boxa,但在下一次迭代中它的值会被覆盖.当click事件触发回调运行时,boxa的值始终是列表中的最后一个元素.

使用闭包(关闭boxa,boxb等的值)将值绑定到单击处理程序的范围.

JSLintJSHint这样的代码分析工具将能够捕获这样的可疑代码.如果您正在编写大量代码,那么花些时间学习如何使用这些工具是值得的.有些IDE内置了它们.

上一篇:Javascript“addEventListener”事件触发页面加载


下一篇:javascript – 单击之前执行的addEventListener单击执行