This question already has answers here:
JavaScript closure inside loops – simple practical example

(44个答案)


7年前关闭。




我有这样的JavaScript代码,这总是给我一个问题
    for(var i=1;i<9;i++){
        document.getElementById('element'+i).onclick=function(){
             theFunc(i)
        }
    }

它选择正确的元素并添加onclick。但是,当我在控制台中键入document.getElementById('element1").onclick时,它将返回theFunc(i)(不是theFunc(1))

因此,无论单击哪个元素,它都将始终调用theFunc(9)(最后我是9)

我的代码有什么问题?

最佳答案

您发现,事件处理程序函数对i有持久的引用,而不是其值的副本。

为了防止这种情况,请将该函数关闭在其他不会改变的地方:

for(var i=1;i<9;i++){
    document.getElementById('element'+i).onclick=makeHandler(i);
}

function makeHandler(index) {
    return function() {
        theFunc(index);
    };
}
makeHandler创建一个函数,该函数关闭index,它是i值的副本,因此在循环继续进行时不会更改。每个事件处理程序都有自己的index

就是说,创建一堆实际上相同的事件处理程序函数通常意味着您可以重新设计一点并仅使用一个处理程序函数。例如,在这种情况下,您可以执行以下操作:
for(var i=1;i<9;i++){
    document.getElementById('element'+i).onclick=theHandler;
}

function theHandler() {
    func(parseInt(this.id.replace(/\D/g, ''));
}

...从元素的id中获取要使用的值。

另一种方法是委托(delegate),您实际上将click事件卡在祖先元素上(所有这些elementX都有一个共同点),然后在发生单击时,查看event.target及其祖先,以了解您应该做什么。

10-04 10:32