for循环中给dom绑定事件的坑
原生js给dom绑定监听事件很简单, dom.onclick=fn, 如果用到了for循环去遍历需要注意啥?
html
<html>
<body>
<ul>
<li name="item1">1</li>
<li name="item2">2</li>
<li name="item3">3</li>
<li name="item4">4</li>
<li name="item5">5</li>
</ul>
</body>
<script>
var lis = document.getElementsByTagName("li")
for(var i=0 ; i < lis.length ; i++ ) {
var item=lis[i]
var attr_name=item.getAttribute("name")
item.onclick=function(){
console.log(attr_name);
}
}
</script>
</html>
在这段代码就出现了一个问题,不管点击哪个li打印出的attr_name
值都是item5
,因为在使用for循环的时候给dom绑定的函数里引用的attr_name
被改变,知道循环结束之后,才确定attr_name
的值.也就是attr_name='item5'
解决1
使用es6的let,用来声明局部变量
js
var lis = document.getElementsByTagName("li")
for(var i=0 ; i < lis.length ; i++ ) {
var item=lis[i]
let attr_name=item.getAttribute("name")
item.onclick=function(){
console.log(attr_name);
}
}
解决2
使用立即执行函数(兼容性好)
立即执行函数可以让函数在创建后立即执行,这种模式本质上就是函数表达式(命名的或者匿名的),在创建后立即执行。立即执行函数只有一个作用:创建一个独立的作用域。这个作用域里面的变量,外面访问不到(即避免了「变量污染」)。
js
var lis = document.getElementsByTagName("li")
for (var i = 0; i < lis.length; i++) {
(function (item) {
var attr_name = item.getAttribute("name")
item.onclick = function () {
console.log(attr_name);
}
})(lis[i]);
}