JS 函数的执行时机

221 阅读1分钟

同步

let a = 1
function fn() {console.log(a)}
//undefinded

声明变量a,赋值为1>声明函数fn>函数未执行,不打印结果

let a = 1
function fn() {console.log(a)}
fn()
a = 2
//1

声明变量a,赋值为1>声明函数fn>执行fn(),打印出a>将2赋值给a

let a = 1
function fn() {console.log(a)}
a = 2
fn()
//2

声明变量a,赋值为1>声明函数fn>将2赋值给a>执行fn(),打印出a

异步

let i = 0
for(i = 0; i<6; i++){
    console.log(i)
}//012345

众所周知,上面的代码最终得到的结果为0,1,2,3,4,5。如果在代码中加入setTimeout()时,结果为6个6

let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
 },0)
}

原因是每次执行 for 循环的时候,setTimeout 都会执行一次,但里面的函数不执行,等到 for 循环执行完,再去执行 setTimeout() 里的函数,所以是打印出6个6,即:

  1. i赋值为0
  2. 判断i < 6,满足条件进入第一个循环
  3. setTimeout()执行,里面的函数过一会执行,跳过setTimeout()继续执行
  4. 执行i++,此时i=1
  5. 判断i < 6,满足条件进入第二个循环
  6. setTimeout()执行,里面的函数过一会执行,跳过setTimeout()继续执行
  7. ···
  8. 执行i++,此时i的值为6
  9. 判断i < 6 ?,不满足跳出循环
  10. 执行第一次循环的setTimeout() //打印出a
  11. 执行第二次循环的setTimeout() //打印出a
  12. ···
  13. 结束

如果非要在setTimeout()时打印出0,1,2,3,4,5呢

  • let声明放入for循环里
for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
 },0)
}
  • 闭包
let i 
for(i = 0; i<6; i++){
  !function(x){
      setTimeout(()=>{
        console.log(x)
      },0)
 }(i)
}
  • for循环里在声明一个x = i
let i 
for(i = 0; i<6; i++){
  let x = i
  setTimeout(()=>{
    console.log(x)
 })
}
  • 利用setTimeout()的第三参数
let i 
for(i = 0; i<6; i++){
  setTimeout((x)=>{
    console.log(x)
 },0,i)
}