JS函数的运行机制

145 阅读1分钟

一、现象

本文主要简单探讨一下JS的执行机制问题,先来看一个小白在学习JS时比较难理解的代码:

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

在最开始学习时,都会认为这段代码的结果应该是打印出 0, 1, 2, 3, 4, 5,实际结果却是 6个6。

二、原因

  • 为什么结果会有 6 这点和setTimeout的调用机制有关(JS的异步执行),setTimeout是在 for循环结束之后执行的,而for循环结束之时,i已经变成了6,因为当i = 5时,for循环条件仍然成立,会再执行一次 i++,最终 i = 6,而这个值已经超出for循环条件,此时for循环结束,setTimeout将6打印出来。

  • 为什么有6个6 setTimeout的意思是设个闹钟,等一会儿再打印i,for实际执行了0,1,2,3,4,5次,而每一次setTimeout都设了个闹钟打i(设了6个闹钟),先按住不表,等到for循环结束后,此时i已经变成 6 了,闹钟依次响起,conger打印出 6个6

三、如何打印出 0,1,2,3,4,5

主要思想是通过作用域,有两种方法:

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

对i的声明放在for循环内部,那么每次次循环都会声明一个新的i,并形成一个块级作用域,6个作用域互不影响,所以每一个i的值都得到了保留。

  • 方法2
for(var i = 0; i < 6; i++ ){
  !function (j){
    setTimeout(() => {
      console.log(j)
    },0)
  }(i);
}
//0,1,2,3,4,5

使用立即执行函数,在每次循环时,都会形成一个立即执行函数。