如何获得与使用 "let" 或 with 块中声明的变量相同的方式工作的变量?

How to get a variable that works the same way as one declared with "let" or in a with block?

我不确定如何称呼这种安排,但这是一个常见问题 - 如果我这样做:

var buttons = document.querySelectorAll(".button"); //select a bunch of buttons
for (var i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener("mouseup", function(){
        alert(buttons[i].getAttribute("data-message"));
    }); 
}

它正在创建一堆匿名函数,每个按钮一个以在 buttons 属性中显示消息,buttons[i] 必须在循环中捕获但会出现 "undefined"

我知道的 2 种方法是 1:let 语句

var buttons = document.querySelectorAll(".button"); //select a bunch of buttons
for (let i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener("mouseup", function(){
        alert(buttons[i].getAttribute("data-message"));
    }); 
}

工作正常,以及 2: with statement

var buttons = document.querySelectorAll(".button"); //select a bunch of buttons
for (var i = 0; i < buttons.length; i++) {
    with ({"button":buttons[i]}) {
        button.addEventListener("mouseup", function(){
            alert(button.getAttribute("data-message")); 
        }); 
    }
}

工作正常。但问题是,我遇到了一个雇主,他对兼容性的期望处于下一个该死的水平,所以 "let" 已经过时了,因为它在技术上仍然不是标准的,而 "with" 也因为它被弃用而过时了.

这让我不知道如何以一种好的方式处理这种情况,是否有第三种标准选项并且不会被弃用?

如果你需要使用 es5 代码而不从 es6 向下编译,有两种简单的方法:将 buttons 变量转换为数组并使用 forEach 或迭代它创建一个你在 for 循环中调用的小闭包:

选项 1:

var buttons = document.querySelectorAll(".button"); //select a bunch of buttons
Array.prototype.forEach.call(buttons, function(el) {
    el.addEventListener("mouseup", function(){
        alert(el.getAttribute("data-message"));
    }); 
}

或选项 2:

var buttons = document.querySelectorAll(".button"); //select a bunch of buttons
function addButtonListener(j){
    buttons[j].addEventListener("mouseup", function(){
        alert(buttons[j].getAttribute("data-message"));
    }); 
}

for (var i = 0; i < buttons.length; i++) {
    addButtonListener(i);
}

必须在设置按钮后调用此闭包