JS 函数的执行时机

278 阅读2分钟

时机不同,结果不同。 犹如刻舟求剑。

例子 1

  • 代码
let a =1
function fn(){
    console.log(a)
}
  • 问打印出多少?不知道!都还没调用呢

例子 2

  • 代码
let a = 1
function fn(){
    console.log(a)
}
fn()
  • 问打印出多少?1

例子 3

  • 代码
let a = 1
function fn(){
    console.log(a)
}
a = 2
fn()
  • 问打印出多少?2!
  • 函数没执行就让a = 2了哦

例子 4

  • 代码
let a = 1
function fn(){
    console.log(a)
}
fn()
a = 2
  • 问打印出多少
  • 答为1

例子 5

  • 代码
let a = 1
function fn(){
    setTimeout(()=>{
        console.log(a)
    },0)
}

fn()
a = 2
  • 问打印出多少
  • 2
  • setTimeout 意思是尽快(就像你打游戏,先打完才做),自然,console.log在a=2之后

例子 6

  • 代码
let i = 0
for(i = 0;i<6; i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}
  • 问打印多少
  • 不是0,1,2,3,4,5
  • 而是6个6
  • 又是因为setTimeout,先把for循环搞完再console.log(定闹钟)

例子 7

  • 代码
for(let i =0; i<6; i++){
    setTimeout((){
       console.log(i) 
    },0)
}
  • 问打印出多少
  • 答案
    • 是 0、1、2、3、4、5
    • 因为 JS 在for 和 let 一起用的时候会加东西
    • 每次循环会多创建一个 i (真有你的啊JS)

说结论

  1. 函数被调用才会开始执行
  2. 遇到setTimeout时,由于这货是会让代码继续执行下去直到完成才执行setTimeout内容,所以需要for let配合达成我们想要的结果。不用for let 就会出现6个6情况
  3. 不用for let行不行?行

不用for let又用setTimeout,又想012345的结果

  • 已知setTimeout等延迟函数的回调会在循环结束时才会执行。或者说setTimeout会延后他作用的代码
  • 那么我们试试让setTimeout认为他不在一个循环里
function timer1(i) {setTimeout( console.log(i),0)}
for(i = 0; i < 6; i++){timer1(i)}
  • woc,这是为什么呢
  • js中 function 可以提供一段独立的作用域,那我们就可以通过在迭代内使用function会为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用域封闭在每个迭代内部,每个迭代中都会含有一个具有正确值的变量供我们访问。
  • 或者说,在function作用域屏蔽了外部的循环,setTimeout就只能乖乖执行了。