1 解释为什么如下代码会打印 6 个 6
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
// 6 6 6 6 6 6
可以这样理解: 每一次 for 循环, setTimeout 都执行一次,但是里面的函数没有被执行,而是被放到了任务队列里。 for 循环执行了 6 次,就放了 6 次。当主线程执行完成后,才进入任务队列里面执行。这时候因为for循环i=6了,所以输出的全部都是6。
2 写出让上面代码打印 0、1、2、3、4、5 的方法
方法一:let关键字
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
因为在 for 语句里用 let 声明变量是局部变量遵循块作用域,只能在当前函数中,所以每次 for 循环执行时都会生成一个单独的作用域,也会生成一个新的 i ,相当于有 6 个 i。 此时,每次执行 setTimeout() 时都会打印出对应的 i ,因此结果就是 0、1、2、3、4、5 。
方法二:闭包
let i
for(i = 0;i < 6;i++){
!function(i){
setTimeout(()=>{
console.log(i)
},0)
}(i)
} // 0,1,2,3,4,5
- 声明匿名函数 function(value){} 包裹setTimeout()
- 然后再匿名函数前加上运算符!,防止生成新的全局变量
- 在匿名函数后加个()立即调用,并把i当作参数value传入匿名函数进行调用
方法三:利用setTimeout的第三个参数,将i传进去
let i
for(i = 0;i < 6;i++){
setTimeout((value)=>{
console.log(value)
},0,i)
} // 0,1,2,3,4,5
原理 :使用setTimeout的第三个参数可以将自身传给第一个参数也就是匿名函数function(value)中,作为所需要的参数value,value可默认不写而i共传入6次,(0,1,2,3,4,5),通过匿名函数即可打印出 通常不写第三个三处,如果默认不写第三个参数,则不会传入函数
方法四:const关键字
let i
for(i = 0;i<6;i++){
const a = i
setTimeout(()=>{
console.log(a)
})
} // 0,1,2,3,4,5