在JavaScript中存储值,而不是表达式

Store the value, not the expression in JavaScript

本文关键字:表达式 JavaScript 存储      更新时间:2023-09-26

首先,我不太确定如何问这个问题。我有一个元素阵列:

var buttons = publishedWork.getElementsByTagName('button');

每个按钮从▶到◼反之亦然。问题是,我不知道总共会有多少个按钮,我打算用一个for来做:

var currentButton;
for (var i = buttons.length; i;) {
    buttons[--i].onclick = function() {
        if (currentButton === buttons[i]) {
            currentButton.textContent = '▶';
            currentButton = null;
        } else {
            currentButton = buttons[i];
            currentButton.textContent = '◼';
        }
    }
}

但这段代码所做的是,无论我单击哪个按钮,它都会更改第一个按钮的内容,从中我可以得到表达式buttons[i],即存储在currentButton中的表达式,而不是对按钮本身的引用。

所以我的问题是:

这是一个需要通过闭包来解决的问题(我刚刚开始掌握这个话题),还是有其他解决方案?

除非我弄错了,否则它看起来像是常见的"在循环中定义索引相关函数"问题。当onclick函数被调用时,它访问i变量。但当这种情况发生时,i一直在循环中,并且为0。所以所有的点击处理程序都只看到i == 0

为了解决这个问题,您可以创建一个函数来创建点击处理程序:

var currentButton;
function createClickHandler(index) {
    var button = buttons[index];
    return function() {
        if (currentButton === button) {
            currentButton.textContent = '▶';
            currentButton = null;
        } else {
            currentButton = button;
            currentButton.textContent = '◼';
        }
    };
}
for (var i = buttons.length; i;) {
    buttons[--i].onclick = createClickHandler(i);
}

编辑:或者使用Diode的建议:)
我关注的是"闭包中的索引"问题,但Diode的答案要清晰得多,处理它的更好方法是

在点击处理程序中使用thisevent.currentTarget

....
buttons[--i].onclick = function(event) {

      // both `this` and `event.currentTarget` gives the clicked button here

}
....

var currentButton;
for (var i = buttons.length; i;) {
    buttons[--i].onclick = function() {
        if (currentButton === this) {
            ...
            currentButton = null;
        } else {
            currentButton = this;
            ...
        }
    }
}

在其他情况下,您必须先重置当前按钮。

var currentButton;
for (var i = buttons.length; i;) {
    buttons[--i].onclick = function(event) {
        if (currentButton === this) {
            currentButton.textContent = '▶';
            currentButton = null;
        } else {
            if(currentButton){
                currentButton.textContent = '▶';
            }
            currentButton = this;
            currentButton.textContent = '◼';
        }
    }
}