JS 一道setTimeout的题

这是我在segmentfault上看到的一个问题。原问题链接

for (var i = 1; i <= 5; i++) {
        setTimeout(function timer() {
            console.log(i);
        }, i * 1000);
    }

问题

其实我们想得到的结果是1,2,3,4,5,结果却是五个6

执行结果

每隔1秒 输出 i 为6

原因

输出i 为什么为6

JS处理时用的是队列,所以在for循环里只是把每个setTimeout任务添加到队列里,等for循环执行完之后,再去执行setTimeout函数,而此时的i变成了6,所以i输出为6,这是i 为6的理解

为什么会每隔一秒执行

刚进入for循环的时候,i为1,所以相对于现在延迟一秒将timer函数添加到队列当中,然后for循环还要继续啊,并没有等一秒再继续循环啊,然后进行第二次循环,这时候i为2,所以相对于现在延迟两秒将timer函数送进队列。以此类推。for循环的时间忽略不计的话,timer函数就以每秒一次的频率执行啦。

解决办法

  • 办法1
for (var i = 1; i <= 5; i++) {
        (function(j) {
            setTimeout(function timer() {
                console.log(j);
            }, j * 1000);
        })(i);
        
//用闭包来解决:通过一个立即执行函数,为每次循环创建一个单独的作用域
  • 办法2
//把var 改为let,let 每次都会创建一个块级作用域
for (let i = 1; i <= 5; i++) {
        setTimeout(function timer() {
            console.log(i);
        }, i * 1000);
    }
  • 办法3
//类似于方法二,使用setTimeout的第三个参数直接传参
  for (var i = 1; i <= 5; i++) {
    setTimeout(function(i) {
      console.log(i);
    }, i * 1000,i);
  }

办法1用闭包解决,办法2用作用域解决,办法三不常见,但使用的是setTimeout的第三个参数直接传参,对第三个参数不了解的看这里

每天都努力一点点
谢谢你看完


你可能感兴趣的:(JS 一道setTimeout的题)