search

Home  >  Q&A  >  body text

javascript - 看了好几个小时还是想不明白的JS代码(好像是与闭包有关),求解惑!

<body>
<input type="button" value="aaa" />
<input type="button" value="bbb" />
<input type="button" value="ccc" />
<script>
window.onload=function(){
    var aBtn = document.getElementsByTagName('input');
    for(var i=0;i<aBtn.length;i++){
        (function(index){
            aBtn[index].onclick=function(){
                alert(index);
            };
        })(i);
    }
};
</script>
</body>

依次点击三个按钮aaa、bbb、ccc我觉得是3、3、3。但点击三个按钮弹出的是0、1、2,这是为什么呢?我想了好几个小时还是搞不懂......

感谢大伙给我的启发,我到犀牛书(6版)和JS高程(3版)找到了相关的知识,总结一下,劳驾帮我看看我的理解是否正确,感谢!!

<body>
<input type="button" value="aaa" />
<input type="button" value="bbb" />
<input type="button" value="ccc" />
<script>
window.onload=function(){
    var aBtn = document.getElementsByTagName('input');
    for(var i=0;i<aBtn.length;i++){
        show(i);             //在for循环中调用这个函数
    }
    function show(index){    //把函数单提出来,不用立即执行的函数
        aBtn[index].onclick=function(){
            alert(index);
        };
    }
};
</script>
</body>

执行for循环时:
当i=0时,show(0)执行, 此时index=0,==>新建一个活动对象,假设叫show0,里面保存了index=0。
内部函数表达式:aBtn[0].onclick=function(){alert(index);};

当i=1时,show(1)执行,此时index=1,==>新建一个活动对象,假设叫show1,里面保存了index=1。
内部函数表达式:aBtn[1].onclick=function(){alert(index);};

当i=2时,show(2)执行,此时index=2,==>新建一个活动对象,假设叫show2,里面保存了index=2。
内部函数表达式:aBtn[2].onclick=function(){alert(index);};

点击按钮时:
aBtn[0].onclick=function(){alert(index);};
在function(){alert(index);}中,没有找到index,去作用域链下一个活动对象中找,找到show0,这个活动对象中保存着index=0,所以aBtn[0]点击时弹出0。
aBtn[1]和aBtn[2],弹出2、3也和aBtn[0]的工作过程一样。

以上是我目前的认识,不知道对不对,劳驾您帮我看看,谢谢。

天蓬老师天蓬老师2820 days ago374

reply all(8)I'll reply

  • 怪我咯

    怪我咯2017-04-10 15:23:12

    手机不方便打字,提供一下方向:

    1. 闭包
    2. JavaScript的函数调用是传值调用
    3. 函数作用域

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 15:23:12

    问下自己代码为什么这样写

    window.onload=function(){
        var aBtn = document.getElementsByTagName('input');
        for(var i=0;i<aBtn.length;i++){
            (function(index){
                aBtn[index].onclick=function(){
                    alert(index);
                };
            })(i);
        }
    };
    

    而不是这样写

    window.onload=function(){
        var aBtn = document.getElementsByTagName('input');
        for(var i=0;i<aBtn.length;i++){
            aBtn[index].onclick=function(){
                    alert(index);
                };
        }
    };
    

    reply
    0
  • 黄舟

    黄舟2017-04-10 15:23:12

    看看这个本站的闭包介绍
    http://segmentfault.com/a/1190000002805295

    reply
    0
  • 高洛峰

    高洛峰2017-04-10 15:23:12

    你能够自己想到是3,3,3的结果说明你已经了解到 "作用域链" 的原理了。

    代码用引入Index的作用是保存当前i的值;

    个人心得:
    理解 "作用域链" , "闭包",可用转化成 "内存" 分配,访问去深入体会;

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 15:23:12

            (function(index){
                aBtn[index].onclick=function(){
                    alert(index);
                };
            })(i);
    
    

    这段在定义匿名函数的同时立刻调用了,而这个调用是在循环体内的,所以3次调用的i是0、1、2,所以绑定的3个onclick也是0、1、2

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-10 15:23:12

    这就相当于这段代码

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

    每次循环都把当前的i值保存了下来

    reply
    0
  • 黄舟

    黄舟2017-04-10 15:23:12

    这其实是一个闭包的问题,其中一个特性是“一个闭包就是当一个函数返回时,一个没有释放资源的栈区。”,完全可以用这句话解释你的问题。网上关于闭包的解释很多,如果改成这个样子就是你想要的3,3,3

    window.onload=function(){
        var aBtn = document.getElementsByTagName('input');
        for(var i=0;i<aBtn.length;i++){
            aBtn[index].onclick=function(){
                    alert(index);
                };
        }
    };
    

    其实楼上已经写了,我刚刚写,楼上就出来了,汗~~~~

    reply
    0
  • 黄舟

    黄舟2017-04-10 15:23:12

    闭包所接受的变量,是父函数变量的结果,不是过程

    reply
    0
  • Cancelreply