Skip to content

for循环中的setTimeout

js
for(var i = 0; i < 3; i++){
    setTimeout(() => {
        console.log(i);
    }, 1000);
}

//最终输出:3 3 3

为什么不输出 1 2 3,原因如下:

js
// var 会产生变量提升,setTimeout处于全局作用域下
/* 相当于每次输出的是已经被改变过的i变量 */
var i;
for(i = 0; i < 3; i++){
    setTimeout(() => {
        console.log(i);
    }, 1000);
}

解决方法:

js
// 方法1:使用let关键字(最佳实践)
for(let i = 0; i < 3; i++){
    setTimeout(() => {
        console.log(i);
    }, 1000);
}
// 方法2:使用闭包,自执行函数新创造了一个函数作用域,每次循环都是一个函数作用域。
for(var i = 0; i < 3; i++){
    (function(i){
        setTimeout(() => {
            console.log(i);
        }, 1000);
    })(i);
}

循环添加事件

html
<ul id="ul">
    <li>li1</li>
    <li>li2</li>
    <li>li3</li>
</ul>

假设以后的li越来越多,并且还可能动态添加新li,期望li添加进去也有事件监听。

js
// 方法1: 事件委托
var ul=document.getElementById('ul');
ul.onclick = function(e){
    if(e.target.tagName === 'LI'){
        console.log(e.target.innerHTML);
        var children=Array.prototype.slice.call(ul.children);//将伪书组转为数组
        var i =children.indexOf(e.target);
        console.log(i);
    }
}

// 方法二: 循环添加事件
const lis=document.querySelectorAll('li');
for(var i = 0; i < 3; i++){
    (function(i){ 
        lis[i].onclick = function(){
            console.log(i);
        }
    })(i)
}

// 方法3:使用let

MIT License