addEventListener using for loop and passing values
我试图使用for循环向多个对象添加事件侦听器,但最终所有侦听器都指向同一对象——>最后一个对象。
如果我通过为每个实例定义boxa和boxb来手动添加监听器,那么它就工作了。我想是循环的addEvent没有按我希望的方式工作。也许我完全使用了错误的方法。
使用class="container"的4个示例容器4上的触发器按预期方式工作。容器1、2、3上的触发器容器4上的触发器事件,但仅当已激活触发器时。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // 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); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <p class="triggerClass">some text </p> <p class="triggerClass">some text </p> <p class="triggerClass">some text </p> <p class="triggerClass">some text </p> |
关闭!D
此固定代码按您的预期工作:
1 2 3 4 5 6 7 8 9 10 | 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 } |
为什么要修复它?
1 2 3 4 5 6 7 8 | 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。解释如下:
1 2 3 4 5 6 7 8 9 | 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); } |
由于变量提升,
当代码运行时,会发生以下情况:在
使用一个闭包(关闭
JSlint或JShint等代码分析工具将能够捕获这样的可疑代码。如果你写了很多代码,花点时间学习如何使用这些工具是值得的。有些IDE内置了它们。
您将面临范围/关闭问题,因为
要解决此问题:
1 2 3 4 5 6 7 8 | function makeItHappenDelegate(a, b) { return function(){ makeItHappen(a, b) } } // ... elem[i].addEventListener("click", makeItHappenDelegate(boxa,boxb), false); |
可以使用函数绑定。不需要使用闭包。请参见下面的内容:
之前:
1 2 3 4 5 6 7 8 9 10 11 12 | 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); } } |
后:
1 2 3 4 5 6 7 8 9 10 11 | 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); } } |
因为关闭了。
查看以下内容:https://developer.mozilla.org/en-us/docs/web/javascript/closures在循环中创建闭包常见错误
示例代码和您的代码本质上是相同的,对于那些不知道"闭包"的人来说,这是一个常见的错误。
简单来说,当您在
因为处理程序"记住"
因此,当调用处理程序时,它将使用
我之前也遇到过这个问题。我通过在循环外部使用一个"添加"函数来解决这个问题,以分配事件,并且它工作得很好。
你的剧本应该是这样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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"; } |