Skip to content
On this page

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]);
}