JS 函数的执行时机

352 阅读2分钟

我们都知道JS的函数有许多关键的要素,如调用时机、作用域、形式参数、调用栈、函数提升等等。但当我们学习JS函数时,第一个需要明确的要素就是其调用时机,也即执行时机。我们先来看看以下这个例子:

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

当我们执行以上函数时,JS会先声明一个 i 变量,并令它的值等于 0 ,然后依次执行 for 循环—— 先让 i 等于 0 ,然后判断 i 是否小于 6 ,若是,则执行 setTimeout 方法稍后打印出 i 的值,并且 i++ ;若不是,则结束循环。

image.png

但是!

由于 setTimeout 方法的延迟性, i 的值并不会在每一次的 for 循环中打印出来,而是会等整个 for 循环结束之后再打印 i 的值。但是每执行一次 for 循环,就会有一个 i 的值会被打印,总共执行了 6 次,故会有 6 个 i 的值被打印出来。而每一次循环中 i 的值会稍后再打印,所以每次 i 被打印时它就已经执行了 6 次 i++ ,所以打印出来的值将会是 6 个 6 。

那么我们有没有办法在不改变 for、let 组合的情况下,使函数依次打印出 0,1,2,3,4,5 呢?

当然可以。

我们只需要把 let 放进 for 循环中,那么就可以视作每次的 i 的值都是一次完整的函数执行,让 setTimeout 不用等整个 for 循环再执行。

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

image.png

那还有没有什么其他方法可以使函数依次打印出 0,1,2,3,4,5 呢?

有的,那就是加入一个立即执行函数让它能够保存每一次 i 的值,这样能够保证在跳出循环体后依然可以打印出之前保存的 i 的值。

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

image.png

©本总结教程版权归作者所有,转载需注明出处