循环中的 addEventListener 不适用于 IIFE

addEventListener on loop not working with IIFE

在下面的代码中,j 的值始终设置为迭代的最后一次。我已经在使用 IIFE,但它仍然给出了非预期的行为。我做错了什么吗?

function renderUsers(users) {
    const frag = document.createDocumentFragment();
    const userList = document.getElementById('user-list');

    // Create and append all the users on the user list
    for (var j = 0; j < users.length; j++) {
        var item = document.createElement('li');
        var division = document.createElement('div');
        var userName = document.createElement('span');
        var deleteButtonAnchor = document.createElement('a');
        var deleteButton = document.createElement('i');
        deleteButton.classList.add('material-icons');
        deleteButton.textContent = 'delete_forever';
        (function() {
            deleteButton.addEventListener('click',function() {
                console.log(j);
            });
        })();
        deleteButtonAnchor.appendChild(deleteButton);
        division.appendChild(userName);
        division.appendChild(deleteButtonAnchor);
        item.appendChild(division);


        userName.appendChild(document.createTextNode(users[j].name.first+' '+users[j].name.last));
        frag.appendChild(item);
    }
    userList.appendChild(frag);
}

你想用闭包做的是将迭代变量作为参数传递,这样:

 (function(j) {
     deleteButton.addEventListener('click',function() {
          console.log(j); // j is the parameter
     });
 })(j);

或者正如@torazaburo 在评论中所注意到的那样,您可以对迭代变量使用 let 关键字来消除创建闭包的需要。有关 let 关键字的更多信息,您可以找到 here。但请注意,这是 ES6 功能,在旧版浏览器中未实现,因此您可能需要先转换它(例如使用 babel)。