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)
}
本文参考摘录了: