addEventListener使用循环和传递值

我正尝试添加事件监听器使用for循环的多个对象,但最终所有的监听器针对同一个对象 – >最后一个。

如果我通过为每个实例定义boxa和boxb来手动添加侦听器,它将起作用。 我想这是addEvent for-loop,这不是我所希望的。 也许我完全用错了方法。

使用class =“container”中的4的示例容器4上的触发按其应有的方式工作。 触发容器1,2,3上的容器1,2,3触发事件,但只有在触发器已被激活的情况下。

任何帮助将不胜感激

点击运行function:

function makeItHappen(elem, elem2){ var el = document.getElementById(elem); el.style.transform = "flip it"; var el2 = document.getElementById(elem2); el2.style.transform = "flip it"; } 

自动加载function添加监听器:

 function addEvents(){ 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); } } 

HTML代码

 <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); } 

由于variables提升 , var声明被移动到范围的顶部。 由于JavaScript没有块范围(例如, if ,等等),他们被移动到函数的顶部。 更新:从ES6开始,您可以使用let来获取块范围的variables。

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

使用闭包(closuresboxaboxb等的值)将值绑定到click处理程序的范围。


代码分析工具,如JSLint或JSHint将能够捕获像这样的可疑代码。 如果你写了很多代码,花时间学习如何使用这些工具是值得的。 一些IDE有内置的。

你面临的范围/closures问题作为function(){makeItHappen(boxa,boxb);} boxaboxb引用,然后总是最后一个元素(S)。

要解决这个问题:

 function makeItHappenDelegate(a, b) { return function(){ makeItHappen(a, b) } } // ... elem[i].addEventListener("click", makeItHappenDelegate(boxa,boxb), false); 

你可以使用函数绑定。你不需要使用闭包。参见下面:

之前

 function addEvents(){ 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); } } 

之后

 function addEvents(){ 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", makeItHappen.bind(this, boxa, boxb), false); elem[k].addEventListener("click", makeItHappen.bind(this, boxa, boxb), false); } } 

这是因为closures。

看看这个: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Creating_closures_in_loops_A_common_mistake

示例代码和代码基本相同,对于那些不知道“closures”的人来说,这是一个常见的错误。

简单来说,当你在addEvents()里面创build一个处理函数时,它不仅仅是从addEvents()的环境中访问variablesi ,而且还会“记住” i

而且因为你的处理程序“记得” i ,variablesi不会在addEvents()执行后消失。

所以当处理程序被调用时,它将使用i但variablesi现在,在for循环后,3。

我前一阵子也有这个问题。 我通过在循环之外使用“增加”function来解决它​​,分配事件,并完美的工作。

你的脚本应该看起来像。

 function addEvents(){ 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; //- edit ---------------------------| adds(boxa, boxb); } } //- adds function ----| function adds(obj1, obj2){ obj1.addEventListener("click", function(){makeItHappen(obj1, obj2);}, false); obj2.addEventListener("click", function(){makeItHappen(obj1, obj2);}, false); } //- end edit -----------------------| function makeItHappen(elem, elem2){ var el = document.getElementById(elem); el.style.transform = "flip it"; var el2 = document.getElementById(elem2); el2.style.transform = "flip it"; }