JS for循环绑定事件问题以及闭包
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>for与onclick配合</title>
    <script type="text/javascript">
    window.onload=function(){
        var btn=document.getElementsByTagName("input");
         for(var i=0;i<btn.length;i++){
         btn[i].onclick=function(){
                alert(this.value);
           }    
    }
}
    </script>
</head>
<body>
<input type="button" value="for循环"/>
<input type="button" value="事件处理"/>
<input type="button" value="弹窗显示"/>
</body>
</html>

这段程序在点击了相应的按钮后会显示相应的value值。
但是为什么把alert里改成i后,不管点哪个都显示3,而不是对应的0,1,2呢?
既然i值都是3,那是怎么能正常显示出对应的value的。

7个回答

this就是当前的button对象,直接alert i只能得到for循环后的,要做闭包指向当前执行到的i值

         window.onload = function () {
            var btn = document.getElementsByTagName("input");
            for (var i = 0; i < btn.length; i++) {
                btn[i].onclick = (function (i) {
                    return function () { alert(this.value+"|"+i); }
                })(i);
            }
        }
qq_23140091
Stahuf for循环是在页面加载完后,还没有点击按钮,他自己就已经执行了一遍了,所以alert(i)才会出现3的吗?
3 年多之前 回复
qq_23140091
Stahuf 那onclick和i没有关系,那么btn[i].onclick的意义就仅仅是通过循环给每一个对象都绑定事件而已,就不用自己敲代码一个个绑定事件了呗,不知道我这样理解有没有错
3 年多之前 回复
showbo
支付宝加好友偷能量挖 btn.length的值
3 年多之前 回复
showbo
支付宝加好友偷能量挖 回复Stahuf: xxx.onclick=function函数体里面的this就是当前点击的对象,这个是规定。和i第几没关系,你函数题里面如果使用到i那就是btn.length的中
3 年多之前 回复
qq_23140091
Stahuf 我有一个地方没有理解就是:this表示当前对象,但是有三个对象,他怎么知道是哪一个对象?我理解的是btn是一个对象数组,this应该要通过btn[i].onclick里面的i来确定是哪一个对象(btn[0] btn[1] btn[2]分别对应一个对象),但是i实际是3,btn[3]是不存在的,所以点击按钮时怎么还能显示对应value的值?
3 年多之前 回复

<!DOCTYPE html>



for与onclick配合
<br> window.onload=function(){<br> var btn=document.getElementsByTagName(&quot;input&quot;);<br> for(var i=0;i<btn.length;i++){<br> btn[i].onclick=function(){<br> alert(this.value);<br> } <br> }<br> }<br>






这是代码
for (var i = 0; i < btn.length; i++) { }   <====>   var i = 0; for(i;i<btn.length;i++){ }
在onload里面,你可以把for循环中的i当做一个局部全局变量,i在栈内存中有下面的变化:
在栈中寻找是否存在值为0的指针,如果有,让i指向这个地址,如果没有,创建一个,然后
让i指向它,当循环一次向后执行时,i依次指向了不同的值,但是这个变化过程中i只是引用
着不同的地址,当循环执行完,当然,i保存了3, alert(i);当然会弹出3,为了解决它,可以
使用闭包:
btn[i].onclick = (function (i) {
                return function () { alert(this.value+"|"+i); }
            })(i);

首次,你要明白作用域的问题,alert中的这个this指向的是什么,这里的this指向的就是botton,其次,你要明白匿名函数什么时候执行,你的这段
代码中的匿名函数是在整段代码执行完了之后才执行的,所以i不会是当前你点击的这个i,最后,你要明白for循环的执行机制,这个i为什么是3,因为for(var i=0;i<btn.length;i++)的最后一次i++让i变成了3,所以你alert的那个时候i已经变成了3。
解决方法上面已经有人做出了回答,这个是经典的闭包问题,试着自己理解一下

理解this和执行时机 这个问题就解决了;还有啊好像在es6之前js没有块级作用域

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


var btn=document.getElementsByTagName("input");这句话有问题,页面里有三个input,由于js不知道你要执行哪一个,js会依次执行所有的input,每当执行下一个的时候就会把上一个覆盖掉,所以当你执行到最后一个的时候就会把前面的全部覆盖掉,正常情况下你应该给这些input分别设置id,这些id可以有规律。然后
document.getElementsById("想要执行的input的id")就行了

qq_23140091
Stahuf 但是一个正规的页面上有好些个按钮,用ById的方法的话,每个input对象都要写一次方法来获取,代码太冗长了吧,没有循环方便吧
3 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问