如何在循环中添加带有局部变量的 eventHandlers

How to add eventHandlers with local variables in a loop

提问人:Tobl 提问时间:9/4/2019 更新时间:9/4/2019 访问量:32

问:

我敢肯定我曾经知道这一点,但我已经离开一段时间了,我再也想不通了。

假设我有一个按钮集合(“按钮 A”、“按钮 B”、“按钮 C”,由 .getElementsByClassName(“button”) 检索的 NodeList 表示。

我现在想向其中添加一个 EventHandler,它利用了在创建处理程序时按值传递的一些局部变量。对于一个最小的示例,让我们使用:

for (var i = elems.length - 1; i >= 0; i--) {
    var inner = elems[i].innerHTML;
    elems[i].onclick = function(){window.alert("Clicked on "+inner+" which is element number "+i)};
}

这里想要的结果是,当单击按钮 B 时,我得到

Clicked on Button B which is element number 1

但是,所有按钮都会屈服

Clicked on Button A which is element number -1

我理解为什么会发生这种情况,但是我需要如何更改代码才能实现前者?如果这是相关的,在最终的事件处理程序中,i 本身不会被使用,而是再次引用 elem[i],它被作为参数传递到处理程序中。

JavaScript 作用域 dom-events 传递值

评论

0赞 Krishna Prashatt 9/4/2019
递减循环而不是递增循环的具体原因是什么?
0赞 Tobl 9/4/2019
当顺序无关紧要时,只检查一次数组长度被认为是最佳实践。不确定它是否仍然如此。
1赞 traktor 9/4/2019
循环中 JavaScript 闭包的可能副本 – 简单的实际示例

答:

1赞 Mamun 9/4/2019 #1

用于声明变量。这将为变量创建一个块作用域,并在循环中保留正确的值:let

for (let i = elems.length - 1; i >= 0; i--) {

演示:

let elems = document.querySelectorAll('button');
for (let i = elems.length - 1; i >= 0; i--) {
  var inner = elems[i].innerHTML;
  elems[i].onclick = function(){window.alert("Clicked on "+inner+" which is element number "+i)};
}
<button type="button">Button A</button>
<button type="button">Button B</button>
<button type="button">Button C</button>

评论

0赞 Tobl 9/4/2019
谢谢。事实证明,当我在 JS 中更活跃时,我也不知道这一点。让有点新吗?
1赞 Mamun 9/4/2019
@Tobl,非常欢迎您,是的,这是相对较新的(ES6)功能。
0赞 vaishali 9/4/2019 #2
var elems = document.getElementsByClassName('btn');
for (var i = elems.length - 1; i >= 0; i--) {
  (function(i) {
    var inner = elems[i].innerHTML;
    elems[i].onclick = function(){window.alert("Clicked on "+inner+" which is element number "+i)};
  })(i);
}

<button type="button" class="btn">Button A</button>
<button type="button" class="btn">Button B</button>
<button type="button" class="btn">Button C</button>