javascript 设置 onclick 以在循环中使用变量的当前值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6048561/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 19:16:54  来源:igfitidea点击:

Setting onclick to use current value of variable in loop

javascriptvariablesloopsscope

提问by Bobby

The title may not make sense and nor would a description alone, so here's a sample of the code:

标题可能没有意义,单独的描述也没有意义,所以这里是代码示例:

for(var a=0;a<10;a++) {
    var b=document.createElement('b')
    b.onclick=function() {
        alert(a)
    }
    b.innerHTML=a
    document.body.appendChild(b)
}

What's odd is that when I set innerHTML to a, it uses the current value of a. So, this code creates ten <b>elements with the values 0, 1, 2, 3, 4, 5, 6, 7, 8, & 9. This works perfectly. What doesn't, however, is the onclick function. It returns the final value of a(10) when any of these elements is clicked. I've tried setting another variable to aand then using that other variable in the onclick event, but still it returns the final value of a. How would I make it use the value of awhen onclick is set?

奇怪的是,当我将innerHTML 设置为a 时,它使用a 的当前值。因此,此代码创建了十个<b>元素,其值为 0、1、2、3、4、5、6、7、8 和 9。这非常有效。然而,onclick 函数没有。a单击这些元素中的任何一个时,它返回(10)的最终值。我已经尝试将另一个变量设置为a,然后在 onclick 事件中使用该另一个变量,但它仍然返回a. 我如何让它使用aonclick 设置时的值?

回答by JaredPar

Try the following

尝试以下

b.onclick= function(arg) {
    return function() {
        alert(arg);
    }
}(a);

The problem you were hitting is that javascript doesn't use block scope. Instead all variables have a lifetime of their containing function. So there was only ever one acaptured in all of the onclickfunctions and they all see it's final value.

您遇到的问题是 javascript 不使用块作用域。相反,所有变量都有其包含函数的生命周期。所以a在所有onclick函数中只捕获了一个,他们都看到了它的最终价值。

The solution works around this by creating a new function and value per scope and then immediately setting that value to the current value of a.

该解决方案通过为每个作用域创建一个新函数和值,然后立即将该值设置为 的当前值来解决此问题a

Here's a version that's a bit expanded and perhaps a bit more readable

这是一个稍微扩展的版本,可能更具可读性

var createClickHandler = function(arg) {
  return function() { alert(arg); };
}

for(var a=0;a<10;a++) {
    var b=document.createElement('b')
    b.onclick = createClickHandler(a);
    b.innerHTML=a
    document.body.appendChild(b)
}

回答by McVitas

One dirty workaround which I found out is to use .valueproperty of the created object to store the argument which we want to pass to .onclickfunction. So I can do something like

我发现的一个肮脏的解决方法是使用.value创建的对象的属性来存储我们想要传递给.onclick函数的参数。所以我可以做类似的事情

for(var a=0;a<10;a++) {
    var b=document.createElement('b')
    b.value=a
    b.onclick=function() {
        myfunc(this.value)
    }
    b.innerHTML=a
    document.body.appendChild(b)
}
function myfunc(n){
  console.log(n)
}

I am not sure if .value works with every element, but it does for DIV for example.

我不确定 .value 是否适用于每个元素,但它适用于例如 DIV。

EDIT: To pass more values then one you can concatenate them using some character like _ and then split it

编辑:要传递更多的值,然后你可以使用像 _ 这样的字符连接它们,然后拆分它

b.value=x+"_"+y+"_"+z

function myfunc(str){
 t=str.split("_")
 x=t[0]
 y=t[1]
 z=t[2]
 console.log(x+","+y+","+z)
}