JavaScript:循环绑定事件-封装函数、闭包解决

提出问题

<ul>
    <li>测试1</li>
    <li>测试2</li>
    <li>测试3</li>
</ul>
<script>
    var lis = document.getElementsByTagName("li")
    for(var i = 0;i<lis.length;i++){
        lis[i].onclick = function(){
            alert(i) // 全部都显示3
        }
    }
</script>

执行结果:点击 li 标签,全部都显示 3

原因:因为js的函数是调用时触发,绑定事件的时候 i 值并没有被传入执行函数里。触发事件时,循环已经结束,此时的 i 值为 索引最大值

解决

方式一:封装函数

// 定义函数
function f(dom,value){ // 此时value的值就确定了,不会随着变量i的值改变
    dom.onclick = function(){
        alert(value)
    }
}
var lis = document.getElementsByTagName("li")
for(var i = 0;i<lis.length;i++){
    f(lis[i],i)// 调用函数,传入变量i
}

方式二:闭包

使用闭包函数存储i值

function f(value){// 此时value的值就确定了,不会随着变量i的值改变
    return function(){
        alert(value)
    }
}
var lis = document.getElementsByTagName("li")
for(var i = 0;i<lis.length;i++){
    // 调用函数,传入变量i
    lis[i].onclick = f(i)
}

原文出处:https://malaoshi.top/show_1IX3noRog4lm.html