关于js批量绑定事件的问题
<body> <ul id="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> <script> var list_obj = document.getElementsByTagName('li'); for (var i = 0; i <= list_obj.length; i++) { list_obj[i].onclick = function() { alert(i); } } </script> </body>
for循环绑定完事件最后执行的时候都是最后一个事件相同,点击的时候弹出的不是0 1 2 3 4,而是5,这是为什么呢 如何解决
原因:当调用onclick
事件的时候,会向上找到i
对象的值。这个时候,由于已经循环完毕,所以i
的值是5
解决方法:
1、闭包
1 for (var i = 0; i <= list_obj.length; i++) { 2 list_obj[i].onclick = (function(i){ 3 return function() { alert(i); } 4 })(i); 5 }
2、ES6
for (let i = 0; i <= list_obj.length; i++) { list_obj[i].onclick = function() { alert(i); } }
关于Let做下说明
下面的代码如果使用var
,最后输出的是10
。
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10
上面代码中,变量i
是var
声明的,在全局范围内都有效。所以每一次循环,新的i
值都会覆盖旧值,导致最后输出的是最后一轮的i
的值。
如果使用let
,声明的变量仅在块级作用域内有效,最后输出的是6。
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
上面代码中,变量i
是let
声明的,当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量,所以最后输出的是6
。你可能会问,如果每一轮循环的变量i
都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i
时,就在上一轮循环的基础上进行计算。