《JS 函数的执行时机》

136 阅读2分钟

先来看几段代码

let a = 1
function fn(){
    console.log('a打印为' +a)
}

fn()
a = 6
fn()
// a打印为1
// a打印为6

看到上面的代码,为什么第一次调用 fn 打印 a 为 1,第二次 却打印 a 为 6 呢?

因为,第一次调用 fn 之前,a 的值确实为 1,但是,第二次调用 fn 的时候,a 被重新赋值为 6 了,所以出现这样的结果。

再看一个例子:

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

fn()
a = 2
// 2

这次为什么 a 不是 1,却为 2 呢?

  • fn 里面有一个 setTimeout 的函数,setTimeout 设置一个定时器,定时器到期后执行一个函数或指定的一段代码。此时 setTimeout 有个参数为 0,表示 「尽快,马上」 的意思。

  • 接着调用 fn,意思就是 「尽快执行 fn」,然后又将 a 重新赋值为 2。

  • 但是 js 会把代码先执行完,再做 「马上要做的事情」,所以,在调用 fn 之前,a 已经被赋值为 2 了。

下面的这段代码,为什么会打印 6个6?

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

答案是 6个6,这个跟上面的例子同理,在 for 循环完 i 以后,再 「尽快打印 i」,这时的 i 已经变成 6 了,所以打印出 6个6。

如何让上面的代码打印 0~5 呢?

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

只需要把 let i = 0 放进 for 里面就可以实现了。这是 JS 为了迎合新手而发明的方法。

除了使用 for let 配合,还有什么其他方法可以打印出 0~5

用立即执行函数

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