JS 函数的执行时机

377 阅读2分钟

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

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

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

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

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

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

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

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

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

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