如何使用闭包将事件绑定到循环中的元素数组

How to bind events to an array of elements in a loop using closure?

本文关键字:循环 元素 数组 绑定 何使用 闭包 事件      更新时间:2023-09-26

我相信每个使用javascript的人都会遇到这个问题,但是因为我真的不知道闭包是如何工作的,所以我不能自己解决这个问题。

    var hint = ["str", "str", "str", "str", "str"];
    var inputIDs = ["ip-name", "ip-pwd", "ip-pwd-cfm", "ip-email", "ip-phone"];
    var errorMsg = [];
    for (var i = 0; i<hint.length; i++) {
        document.getElementById(inputIDs[i]).addEventListener("focus", function (e) {
            var tar = e.target.parentElement.getElementsByClassName("alert")[0];
            tar.innerHTML = hint[i];
        });
    }

我想迭代地将焦点事件绑定到每个元素。但是如果我使用上面的代码,每次执行函数时,i等于5。

我认为我应该在这里使用闭包来获得i的值,如我想要的。

谁能给个建议?

在循环中创建一个闭包并与i绑定

var hint = ["str", "str", "str", "str", "str"];
var inputIDs = ["ip-name", "ip-pwd", "ip-pwd-cfm", "ip-email", "ip-phone"];
var errorMsg = [];
for (var i = 0; i < hint.length; i++) {
  (function(i) { // creating a closure
    document.getElementById(inputIDs[i]).addEventListener("focus", function(e) {
      var tar = e.target.parentElement.getElementsByClassName("alert")[0];
      tar.innerHTML = hint[i];
    });
  }(i))
}

在我看来,更简单和更干净的解决方案是使用forEach,下面是一个工作示例,您可以关注input标记以查看控制台上的结果。

var hint = ["str", "str", "str", "str", "str"];
var inputIDs = ["ip-name", "ip-pwd", "ip-pwd-cfm", "ip-email", "ip-phone"];
var errorMsg = [];
inputIDs.forEach(function(item, i){
  document.getElementById(inputIDs[i]).addEventListener("focus", function(e) {
  console.log(i);
  // I comment out this code just to keep this example more simple  
  //var tar = e.target.parentElement.getElementsByClassName("alert")[0];
  //tar.innerHTML = hint[i];
  });
});
<input id="ip-name" type="text">
<input id="ip-pwd" type="text">
<input id="ip-pwd-cfm" type="text">
<input id="ip-email" type="text">
<input id="ip-phone" type="text">