JS 函数的执行时机不同,那么其结果也不同,这次我们就来讲一讲 JS 函数的执行时机。

    我们来通过一些案例逐步了解 JS 函数的执行时机。

    1. let a = 1
    2. function fn(){
    3. console.log(a)
    4. }
    5. // 这段代码,无法确定打印出的是什么,因为 fn 没有被调用
    1. let a = 1
    2. function fn(){
    3. console.log(a)
    4. }
    5. fn()
    6. // 1
    1. let a = 1
    2. function fn(){
    3. console.log(a)
    4. }
    5. a = 2
    6. fn()
    7. // 2
    8. // a 是一个全局变量,fn 被调用的时候,a 的值变成了 2,此时打印的结果为 2
    1. let a = 1
    2. function fn(){
    3. console.log(a)
    4. }
    5. fn()
    6. a = 2
    7. // 1
    8. // 代码先执行 fn ,然后对 a 的值进行修改,所以打印出的值还是 1
    1. let a = 1
    2. function fn(){
    3. setTimeout(()=>{
    4. console.log(a)
    5. }, 0)
    6. }
    7. fn()
    8. a = 2
    9. // 2
    10. // setTimeout 是一个延迟执行的异步函数,即使设置延迟时间为 0 ,也要等所有代码执行完才会执行 setTimeout 内的函数,所以在执行 console.log(a) 时,此时 a = 2 已经执行完毕,所以值为 2

    接下来,我们来看一个面试题

    1. let i = 0
    2. for(i = 0; i < 6; i++){
    3. setTimeout(()=>{
    4. console.log(i)
    5. }, 0)
    6. }

    这段代码的打印结果为 6 个 6,由于 setTimeout 会延迟执行,每次循环执行一次 setTimeout ,在循环结束时,i 的值为 6,此时执行 6 次 console.log(i) ,所以打印出 6 个 6。

    那么,我们如何通过 setTimeout 来打印出 0、1、2、3、4、5 呢?

    目前,我可以通过如下两种方式来解决这个问题。

    1. for(let i = 0; i < 6; i++){
    2. setTimeout(()=>{
    3. console.log(i)
    4. }, 0)
    5. }
    6. // 0、1、2、3、4、5
    7. // 通过 for let 配合,JS 会在 for 循环里再创建一个 i 变量,用于临时存储。
    8. // 而 setTimeout 接收到的 i 就是这个临时被创建的变量 i,所以结果为 0、1、2、3、4、5
    1. let i = 0
    2. for(i = 0; i < 6; i++){
    3. !(function (i){
    4. setTimeout(()=>{
    5. console.log(i)
    6. }, 0)
    7. }(i))
    8. }
    9. // 0、1、2、3、4、5
    10. // 这种方法我们可以理解为第一种方法对临时变量的解释
    11. // 通过立即执行函数,来获取一个临时变量 i ,根据作用域的就近原则,打印的 i 就是 临时变量 i

    以上就是打印 0、1、2、3、4、5 的方法,如有其他方法,欢迎补充!