循环索引奇异性的JavaScript

循环索引奇异性的JavaScript,javascript,for-loop,onclick,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++)

我对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>

window.onload=函数(){
var buttons=document.getElementsByTagName('a');

对于(var i=0;i而言,这是一个执行顺序问题


基本上,单击处理程序在循环退出后很好地访问
i
,因此
i
等于
2

,您需要存储
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);
    }
}
window.onload=函数(){
var buttons=document.getElementsByTagName('a');
for(var i=0;i您在
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);
}
函数makeOnClickCallback(i){
返回函数(){
警报(一);
返回false;
};  
} 
var i;
对于(i=0;i<2;i++){
按钮[i].onclick=makeOnClickCallback(i);
}
如果您不熟悉闭包的工作原理,这可能是一个相当棘手的话题。您可以查看以下Mozilla文章以获得简要介绍:



注意:我还建议不要在
for
循环中使用
var
,因为这可能会欺骗您相信
I
变量具有块作用域,而另一方面
I
变量就像
按钮
变量一样,作用域在函数中。

这也是一个作用域问题,
I
在不太明显的情况下仍然存在。对,这就是为什么我链接到我的一篇关于闭包的帖子。在循环中创建函数不是recommended@Ryan:我不确定这是迂腐还是混乱。你在重复JSLint/JSHint警告,却没有花时间理解它的含义。请查看不应在循环中创建函数的示例。IIFE是可接受的,因为在
let
得到普遍支持之前,它几乎是某些场景中的唯一选项。可接受的答案也会在循环中创建函数,但没有否决票或注释?好的,让我澄清一下:您在循环中创建了两个函数。t在一个循环中创建一个函数:点击处理程序。因此,被接受的答案最小化了效率低下,而你的效率最大化了。”瑞安:那么你是迂腐的,因为你在一个微优化上投票失败了,甚至没有一个真正的优化,因为它没有考虑C。ompiler自己的优化。在Chrome的控制台中,iLife在100万次操作中以大约100毫秒的速度出现(我鼓励您检查一下)这一点都不重要,因为这个问题从
i
=
0
循环到
2
,所以差别是无法估量的。恭喜你,你是交通官,因为这家伙在车票过期1秒钟后回到车里,你就给了他停车罚款。:叹气:是的,我想我太迂腐了。所以起诉我吧。带上你的性能、编译器和你的“我是对的,我有126k代表”,在你完美的小世界里尽情跳跃,拥有你想要的一切。请举例说明你是如何用“这”解决问题的