为什么如下代码会打印 6 个 6?
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
/*
setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行
只要主线程执行栈内的同步任务全部执行完成,栈为空就马上执行。
也就是当同步任务的函数和语句执行完后,0秒或者立刻执行setTimeout(fn,0)。
*/
在此段代码中,由于js是单线程语言,所以会首先执行完for循环,循环完毕,执行栈为空就马上执行setTimeout,执行六次
但是,若是把let i=0放到循环语句中
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
//输出结果 0 1 2 3 4 5
因为let变量的作用域只能在当前函数中,所以每次for循环生成的都是一个新的i, setTimeout里输出的i就是这个新的i,这个i是不会变化的,所以输出的就是正常的。
因为在for语句里用let声明变量是局部变量遵循块作用域,所以每次for循环执行时都会生成一个单独的作用域,i的值只会在当前循环内有效,每次会生成一个新的i,相当于有6个 i。 此时,每次执行setTimeout()时都会打印出对应的i,打印结果就是0、1、2、3、4、5了。
除了使用 for let 配合,还有
//闭包
let i
for(i = 0; i<6; i++){
!function(j){
setTimeout(()=>{
console.log(j)
},0)
}(i)
}
//利用 setTimeout 的第三个参数,将i传进去
let i
for(i = 0; i<6; i++){
!function(j){
setTimeout(()=>{
console.log(j)
},0)
}(i)
}
//利用 const 关键字
let i
for(i = 0; i<6; i++){
const x = i
setTimeout(()=>{
console.log(x)
})
}