JS 函数执行的时机不同,得到的结果也会不同。
一般情况
let c = 1
function fn(){console.log('c = ' + c)}
fn()
执行步骤:
- 声明变量
c并为它赋值1 - 声明函数
fn - 执行
fn,打印c = 1 - 结束
let c = 1
function fn(){console.log('c = ' + c)}
c = 2
fn()
执行步骤:
- 声明变量
c并为它赋值1 - 声明函数
fn - 将
2赋值给c - 执行
fn,打印c = 2 - 结束
let c = 1
function fn(){console.log('c = ' + c)}
fn()
c = 2
执行步骤:
- 声明变量
c并为它赋值1 - 声明函数
fn - 执行
fn,打印c = 1 - 将
2赋值给c - 结束
for 循环与 setTimeout
let c = 0
for(c = 0; c<6; c++){
setTimeout(()=>{
console.log(c)
},0)
}
for 循环结束后,并没有得到预期的 1~6 ,而是打印出了六个 6
可以这样理解:
每一次 for 循环, setTimeout 都执行一次,但是里面的函数没有被执行,而是被放到了任务队列里。 for 循环执行了 6 次,就放了 6 次。因为 for 循环结束时 i=6 ,所以输出六个 6 。
- 注:
WindowOrWorkerGlobalScope混合的setTimeout()方法设置一个定时器,该定时器在定时器到期后执行一个函数或指定的一段代码。 - 又问:
setTimeout()设置的定时器究竟什么时候会过期呢? - 答: 上文的代码中,
setTimeout(()=>{console.log(c),0})可简化为setTimeout(fn,0)形式,在for循环执行完成后,它所设置的定时器就到期了,0代表零秒后执行(立即执行)setTimeout(fn,0)
一定要打印出 0、1、2、3、4、5
可以这样写:
for(let c = 0; c<6; c++){
setTimeout(()=>{
console.log(c)
},0)
}
说明:
因为在 for 语句里用 let 声明变量是局部变量遵循块作用域,所以每次 for 循环执行时都会生成一个单独的作用域,也会生成一个新的 c ,相当于有 6 个 c。 此时,每次执行 setTimeout() 时都会打印出对应的 c ,因此结果就是 0、1、2、3、4、5 。
还可以这样解决:
- 利用
const关键字:
let c
for(c = 0; c<6; c++){
const x = c
setTimeout(()=>{
console.log(x)
})
}
- 闭包:
let c
for(c = 0; c<6; c++){
!function(j){
setTimeout(()=>{
console.log(j)
},0)
}(c)
}
- 利用
setTimeout的第三个参数,将c传进去
let c
for (c = 0; c< 6; c++) {
setTimeout((value) => {
console.log(value)
}, 0, c)
}
本文参考摘录了: