本文将使用一个例子简单地讨论一下函数的调用时机

函数的调用时机不同,结果也不同

首先查看 setTimeout文档

打印666666

为什么以下函数打印出6个6?

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

由于setTimeout会在一段时间以后再执行其内部的函数,所以在跳出循环以后也就是1 === 6时打印 i 的值,即打印6个6

那么怎样让以上代码打印出 0,1,2,3,4,5 呢?

打印012345

只需将 let 换个位置

  1. for(let i = 0; i<6; i++){ // let 到这里来了
  2. setTimeout(()=>{
  3. console.log(i)
  4. },0)
  5. } // out: 0, 1, 2, 3, 4, 5, 6

因为 let 申明的变量是局部作用域,每次循环都是一个新的作用域,就会开辟一个新的空间让 i 指向它,之前的空间得不到释放,形成了闭包,在跳出循环体以后,打印的是之前每个循环中 i 曾经指向的值,等价于

  1. {
  2. let i = 0;
  3. setTimeout(()=>{
  4. console.log(i)
  5. },0)
  6. }
  7. {
  8. let i = 1
  9. setTimeout(()=>{
  10. console.log(i)
  11. },0)
  12. }
  13. // ...

还是打印012345

使用立即执行函数

  1. let i = 0
  2. for(i = 0; i<6; i++){
  3. !function(j){
  4. setTimeout(()=>{
  5. console.log(j)
  6. },0)
  7. }(i)
  8. } // out: 0, 1, 2, 3, 4, 5, 6