循环绑定事件时传递参数值相同的问题
-
在编写JS的时候我们经常会遇到要对一系列元素进行事件绑定,循环对元素的事件进行赋值并根据循环次数传递不同的参数,在这个过程中我们会遇到一个问题,那就每个元素事件运行的时候传递的参数都是相同的值。实际上这里涉及到变量的作用域的问题,可以用闭包来解决这个问题。
-
为了准确说明这个问题,下面用一个例子展示。我们需要点击不同的 li 时,弹出其所在顺序,如,点击First Item,应该弹出提示框 1,点击Sixth Item,应该弹出提示框 6。
<!DOCTYPE html> <html> <head> <title>Test</title> <script> window.onload = function(){ var list = document.getElementById("list").getElementsByTagName("li"); for(var i = 0; i < list.length; i++){ var li = list[i]; //第一种方式,错误的示范:无论点击哪个 li 弹出来的数字都是 7 /* li.onclick = function(){ alert(i + 1); };*/ //第二种方式正确的写法:点击First Item 将会弹出 1,Sixth Item 会弹出 6 li.onclick = (function(index){ return function(){ alert(index + 1); } })(i); }; } </script> </head> <body> <ul id="list"> <li>First Item</li> <li>Second Item</li> <li>Third Item</li> <li>Fourth Item</li> <li>Fifth Item</li> <li>Sixth Item</li> </ul> </body> </html>
- 上述例子中,方式一的写法是常犯的错误,此时 alert 方法中的 变量 i 实际上是指向一个内存地址,从此地址中取值然后 alert 显示,由于 JS 脚本绑定事件在页面加载完成后执行完了循环,因此 i 这个值就是循环结束后的值,即 7 。当我们点击 li 时,弹出了自然就都是 7 了。要解决这个问题,我们应该在每次循环时使用的变量指定一个单独的内存空间来存储值,而不是统一使用一个内存空间,在 JS 中可以通过闭包的方式处理,这就是方式二。