adding 'click' event listeners in loop
在HTML标记中为侦听器重构标准
1 2 3 4 5 6 7 8 | var td; for (var t=1;t<8;t++){ td = document.getElementById('td'+t); if (typeof window.addEventListener==='function'){ td.addEventListener('click',function(){ console.log(td); })} } |
当点击
这是实时代码
您需要在一个闭包中包装事件侦听器的分配,比如:
1 2 3 4 5 6 7 8 9 10 11 | var td; for (var t = 1; t < 8; t++){ td = document.getElementById('td'+t); if (typeof window.addEventListener === 'function'){ (function (_td) { td.addEventListener('click', function(){ console.log(_td); }); })(td); } } |
发生什么事了
变量
从技术上讲:每个事件处理程序函数都是一个闭包——一个引用外部作用域中变量的函数。
一般解决方案此类问题的一般解决方案是从包装函数返回事件处理程序,将要"修复"的变量作为参数传递:
1 2 3 | td.addEventListener('click', function(wrapTD) { return function() { console.log(wrapTD); } }(td)); |
参数现在绑定到被调用包装函数的作用域。
更简单的解决方案:使用EDOCX1[1]不过,还有一个更简单的选择。在事件处理程序中,
1 2 3 | td.addEventListener('click', function() { console.log(this); }); |
更简单的是:没有回路!
最后,您可以完全摆脱
1 2 3 4 5 6 7 8 | var table = document.getElementById('my-table'); table.addEventListener('click', function(e) { if (e.target.nodeName.toUpperCase() !=="TD") return; var td = e.target; console.log(td); }); |
对于较大的表来说,这是一个更好的解决方案,因为您只需要用一个事件处理程序替换多个事件处理程序。请注意,如果将文本包装在另一个元素中,则需要对此进行调整,以检查目标元素是否是
所以这里所发生的是,您将变量"td"保持在事件侦听器函数的范围内。"td"只有一个实例,每次for循环迭代时都会更新该实例。因此,当for循环完成时,td的值现在设置为元素"td7",而事件处理程序只记录td的当前值。
在上面的示例中,您可以简单地记录"this":
1 2 3 4 5 6 7 8 9 | var td; for (var t=1;t<8;t++){ td = document.getElementById('td'+t); if (typeof window.addEventListener==='function'){ td.addEventListener('click',function(){ console.log(this); }); } } |
由于"this"设置为元素,因此为执行事件处理程序绑定了事件。
我猜您在寻找更多关于在for循环中创建闭包时保持迭代器保持不变的答案。为此,您需要在for循环之外定义一个函数。
1 2 3 4 5 6 7 8 9 10 11 12 | for (var t=1;t<8;t++){ bind_event(t); } function bind_event(t) { var td = document.getElementById('td'+t); if (typeof window.addEventListener==='function'){ td.addEventListener('click',function(){ console.log(td); }); } } |
这样,每次运行bind_事件时都会创建一个名为"td"的变量实例,并且该实例将保留在事件侦听器函数的闭包中。值得注意的是,bind_事件中的"t"也是一个新变量。
据我所知,这是因为闭包…您在for语句的范围内分配事件处理程序。当点击发生时,如果td变量在for范围内并写入日志,那么它将获取最后一个版本。
以下各项应按预期工作:
1 2 3 4 5 6 7 8 | for (var t=1;t<8;t++){ var td; td = document.getElementById('td'+t); if (typeof window.addEventListener==='function'){ td.addEventListener('click',function(){ console.log(this); })} } |