js:for循环中的setTimeout

103 阅读1分钟

如下代码打印什么

    for (var i = 0; i < 5; i++) {
      console.log(i)
    }

如你所想,打印0到4

image.png

这样呢?

    for (var i = 0; i < 5; i++) {
      setTimeout(() => {
        console.log(i)
      }, 1000);
    }

1秒后打印5个5

为什么?

for循环是立即执行完的,此时i已经是5了,setTimeout中的函数会等待1秒后执行,执行该函数时,i为5

怎么改,可以输入0到4?

第一种方法:用let定义变量

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

这样,1秒后打印0到4

第二种方法:使用闭包

    for (var i = 0; i < 5; i++) {
      ((i) => {
        setTimeout(() => {
          console.log(i)
        }, 1000);
      })(i)
    }

这样相当于用自执行函数模拟了类似let的块级作用域,所以也是输出0到4

    for (var i = 0; i < 5; i++) {
      (() => {
        setTimeout(() => {
          console.log(i)
        }, 1000);
      })()
    }

使用闭包,但是不传参,那setTimeout中的函数用的i还是var定义的那个i,还是打印5个5

第三种方法:

    for (var i = 0; i < 5; i++) {
      setTimeout(fn(i), 1000);
    }

    function fn(i) {
      console.log(i)
    }

setTimeout中的是函数(fn)的调用,fn会立即执行,此时会立即打印0到4,1秒后什么也不执行