JavaScript for循环索引的陌生感

pyt*_*BOI 15 javascript for-loop onclick

我对JS比较新,所以这可能是一个常见的问题,但在处理for循环和onclick函数时我发现了一些奇怪的东西.我能用这段代码复制问题:

<html>
<head>

<script type="text/javascript">
window.onload = function () {
    var buttons = document.getElementsByTagName('a');
    for (var i=0; i<2; i++) {
        buttons[i].onclick = function () {
            alert(i);
            return false;
        }
    }
}

</script>

</head>

<body>
<a href="">hi</a>
<br />
<a href="">bye</a>

</body>

</html>
Run Code Online (Sandbox Code Playgroud)

点击链接时,我希望得到'0'和'1',但我得到'2'.为什么是这样?

顺便说一句,我设法通过使用'this'关键字来解决我的特定问题,但我仍然对这种行为背后的原因感到好奇.

Dan*_*llo 15

你在循环中遇到了一个非常常见的闭包问题for.

封闭在闭包中的变量共享相同的单个环境,因此在onclick执行回调时,循环已经运行,i变量将指向最后一个条目.

您可以使用函数工厂通过更多闭包解决此问题:

function makeOnClickCallback(i) {  
   return function() {  
      alert(i);
      return false;
   };  
} 

var i;

for (i = 0; i < 2; i++) {
    buttons[i].onclick = makeOnClickCallback(i);
}
Run Code Online (Sandbox Code Playgroud)

如果您不熟悉闭包的工作方式,这可能是一个非常棘手的主题.您可以查看以下Mozilla文章以获得简要介绍:


注意:我还建议不要varfor循环内部使用,因为这可能会让你相信i变量具有块范围,而另一方面i变量就像buttons变量一样,在函数范围内.


And*_*y E 9

您需要存储i变量的状态,因为在事件触发时,范围状态i已增加到最大循环计数.

window.onload = function () {
    var buttons = document.getElementsByTagName('a');
    for (var i=0; i<2; i++) {
        (function (i) {
            buttons[i].onclick = function () {
                alert(i);
                return false;
            }
        })(i);
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的示例使用单个参数创建一个匿名函数,i然后i在作为该参数传递时调用该函数.这将在单独的范围中创建一个新变量,从而保存该特定迭代时的值.