1. 为什么以下代码会打印出 6 个 6
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
// 6*6
要搞清楚这个问题,首先要要了解 JS 函数的执行机制和作用域
-
JS 的执行机制: JS 是单线程环境,是从上到下依次执行的,即 同步执行;for 循环是同步代码,
setTimeout
是 异步代码。JS 在执行代码的过程中,碰到同步代码会依次执行,碰到异步代码就会将其放入任务队列中进行等待,当同步代码执行完毕后再开始执行异步代码,即 异步执行。 -
JS函数作用域:当同步代码执行完毕后,开始执行异步的
setTimeout
代码,执行setTimeout
时需要从当前作用域内寻找一个变量i
,此时 for 循环已执行完毕,当前i=6
,所以执行setTimeout
时输出为 6,任务队列中的剩余5个setTimeout
也依次执行,输出为6。
2. for 循环和 let 配合使用使上面代码打印 0、1、2、3、4、5
示例如下:
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 是不会变化的,所以输出的就是正常的。
3. 其他方法
let i = 0
for (i = 0; i < 6; i++){
function fn(i){
setTimeout(()=>{
console.log(i)
}, 0)
}
fn(i)
}
每次循环都会调用 fn
,每次传入的i
都只保存在当轮循环的 fn
中。由于每次传入的i
的值都不一样,所以每次打出的结果也不会相同。
网友评论