这个为什么弹出来的一直都是3呢?

我想要点哪个就弹出来哪个的序号 可是为什么一直弹3呢?

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style type="text/css">
    div{width: 80px;height: 200px;background-color: #ccc;float: left;margin-left: 10px}
    </style>
    <script type="text/javascript">
        window.onload=function(){
            var oDiv=document.getElementsByClassName('div');
            for(i=0;i<oDiv.length;i++){
                oDiv[i].onclick=function(){
                    alert(i);
                }
            }
        }
    </script>
</head>
<body>
<div class="div"></div>
<div class="div"></div>
<div class="div"></div>
</body>
</html>
阅读 2.3k
4 个回答
        var oDiv=document.getElementsByClassName('div');
        for(let i=0;i<oDiv.length;i++){
            oDiv[i].onclick=function(){
                alert(i);
            }
        }
        

出现一直3的原因是由于i声明为全局变量了,在单击之前,循环已经走完,这时候i为3
用let是最简单直接的方法,因为let实现了js的块级作用域,相当于每次的i都是在循环体内的,不受外界影响,循环可以拆解为

            oDiv[1].onclick=function(){
                alert(1);
            }
            oDiv[2].onclick=function(){
                alert(2);
            }
            oDiv[3].onclick=function(){
                alert(3);
            }
            

升级版

    for(i=0; i<oDiv.length; i++){
        (function(ii){
            oDiv[ii].onclick=function(){
                alert(ii);
            }
        }(i))
    }

。。。因为alert时候已经i是3了。你需要闭包处理以保存变量。

补充

var oDiv=document.getElementsByClassName('div');
for(i=0;i<oDiv.length;i++){
    (function(i){
        oDiv[i].onclick=function(){
            alert(i);
        }
    })(i)
}

这里是使用闭包,先是在for循环中构建了一个立即执行函数,将i当前变量保存在这个函数内,在并且在点击时候alert出来。

click 事件的回调在循环执行完成之后才被绑定,共享一个i,i为循环后的值,可以去看一下js的闭包
另一个比较明显和经典的例子

for (var i = 1; i <= 5; i++) {
    setTimeout(function timer() {
        console.log(i);
    }, i * 1000);
}

可以通过立即执行函数()()或块作用域(let)来解决。就不写例子了
希望能帮到你。

新手上路,请多包涵

这个就是很传统的闭包问题啦
上面的大神已经说得很充分了,我就补充一点我自己理解的时候踩的坑

var closure =function(dom){
            var i=0,len=dom.length; /*保存dom数量,性能好一点*/
            var handler=function(){
                                console.log(i)
                  }
            for(/*var i=0  写在这里实际上和写上面是一样的*/;i<len;){
                  dom[i].onclick=handler
                  i++ //写for里面和写这里是一样的
                  
                /* 没有赋值操作 这样是不是觉得有点不同了*/
            }
            
            }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题