for循环绑定事件时,var和let的区别

案例

html:

<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>

使用 var 绑定事件

let items = document.getElementsByTagName("button");
for (var i = 0 ; i < items.length ; i++){
    items[i].onclick = function(){
        console.log(i,"---",items[i].innerText)
    }
}
console.log(i);   //打印结果是:3

结果: 事件绑定有问题
原因: 这里 var 声明的变量 i 是 全局变量,当事件绑定完退出 for 循环时,i 的值为 3,当鼠标点击触发事件时,找不到 items[3] 这一个对象,所以报错。

验证全局变量

<script>
    for ( var a = 0 ;a<5;a++){

    }
    console.log("window:",window)

</script>

使用 let 绑定事件

let items = document.getElementsByTagName("button");
for (let i = 0 ; i < items.length ; i++){
    items[i].onclick = function(){
        console.log(i,"---",items[i].innerText)
    }
}
console.log(i);   //打印结果是:undefine

结果: 绑定正确
原因: let 是ES6新增的,具有在 当前块级作用域中有效。

等同于: 上述代码可以像下面这样理解,当点击事件发生时,事件函数在自己的作用域里找不到i,于是向上一级找,找到了 i (let不会影响作用域链)

{
    let i = 0;
    items[i].onclick = function(){
        console.log(i,"---",items[i].innerText)
    }
}
{
    let i = 1;
    items[i].onclick = function(){
        console.log(i,"---",items[i].innerText)
    }
}
{
    let i = 2;
    items[i].onclick = function(){
        console.log(i,"---",items[i].innerText)
    }
}