09/24
2016
设想网页上有四个按钮:
<input type="button" value="0"> <input type="button" value="1"> <input type="button" value="2"> <input type="button" value="3">
我们用for循环处理它们时,如果要用到它们对应的序号,则可能出现问题。如下JavaScript代码:
var bts=document.querySelectorAll("input"); for (var i = 0; i <= bts.length - 1; i++) { bts[i].addEventListener("click",function(){ alert(i); }) }
按照设想,当我们点击按钮时,它们会从左到右分别弹出0/1/2/3,但实际上,全部弹出的是4。这里显而易见有两个问题:
1.为什么弹出的数字都一样;
2.为什么弹出的是4。
其实原因是同一个,那就是for循环里的i是贯穿其整个作用域的。我们给4个按钮分配的i是同一个变量,当这个变量变了的时候,4个按钮上绑定的i都变了。for循环从开始运行到结束,i的值依次是0/1/2/3/4(到4的时候停止运行),最后定格在了4。当我们在for循环执行完之后去点击按钮,i已经是4了,所以全部弹出的是4。
我们可以利用立即执行函数(匿名函数)来创建独立作用域,把每个按钮的事件都在独立作用域里绑定。并且我们绑定时不直接使用i,而是把i的值传递进去进行绑定。这样就可以解决上面的问题。代码如下:
var bts=document.querySelectorAll("input"); for (var i = 0; i <= bts.length - 1; i++) { !function(ii){ bts[i].addEventListener("click",function(){ alert(ii); }) }(i) }
这里面除了用立即执行函数包裹了绑定过程,还有个地方要注意,就是这个立即执行函数要有个参数,然后在执行它时把i作为参数传递进去。这样,绑定事件时所使用的ii是具体值,而非变量i。
之后,我们点击按钮,发现依次弹出0/1/2/3,问题得以解决。