JS中的let与for循环

465 阅读1分钟
let i = 0
for( i = 0; i < 6; i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}
​
// 输出6个'6'

setTimeOut需要浏览器提供的计时器线程来计时,属于异步任务。JavaScript属于单线程语言,将setTimeOut交给浏览器计时后,自己会转到执行主线程的代码,即上面例子中的for循环,当循环执行完成后,读取异步消息队列里的任务setTimeOut,由于全局定义了一个i,所以此时,i = 6,共有6个setTimeOut,输出6个6

for( let i = 0; i < 6; i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}
​
//输出 0,1,2,3,4,5

此时看上去也只是定义了一个i,为啥输出结果会不一样?

因为

JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

这个是JavaScript底层实现的,类似于

let i = 0if( 0 < 6 ){
    let k = i; // 底层实现
    setTimeout(()=>{
        console.log(k)
    },0)
}
 i++;
if( 1 < 6 ){
    let k = i;
    setTimeout(()=>{
        console.log(k)
    },0)
}

除了在for循环中使用let定义变量,还可以用闭包实现输出0-5

let i;
for( i = 0; i < 6; i++){
    function fn(i){
        setTimeout(()=>{
            console.log(i)
        },0)
    } 
    fn(i)
}