搜索

首页  >  问答  >  正文

javascript - js 入坑题目:setTimeout()函数执行完结果却是五个6的原因是?

setTimeout()函数执行完结果却是 五个6 的原因是?

1

2

3

4

5

6

<code> for (var i = 1; i <= 5; i++) {

        setTimeout(function timer() {

            console.log(i);

        }, i * 1000);

    }

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

虽然用js 闭包解决了问题,得到想要的1,2,3,4,5,但还是不明白上述的代码为什么出现五个6?

1

2

3

4

5

6

7

8

<code> for (var i = 1; i <= 5; i++) {

        (function(j) {

            setTimeout(function timer() {

                console.log(j);

            }, j * 1000);

        })(i);

         

//通过一个立即执行函数,为每次循环创建一个单独的作用域</code>

黄舟黄舟2872 天前863

全部回复(3)我来回复

  • PHPz

    PHPz2017-05-19 10:49:29

    首先需要明白的一点JS的任务机制是队列机制。

    所以没走一次for循坏只是把setTimeout这个任务放到队列后面,即setTimeout里面执行的代码只会在执行完for循坏才会执行,所以那个时候i的值就是不满足for循坏的值,才会去执行setTimeout的代码。

    个人看法,有什么说的不对的欢迎指出

    回复
    0
  • 天蓬老师

    天蓬老师2017-05-19 10:49:29

    var 改为 let 即可

    var 是全局定义,i 没有构成闭包,log(i)都是打印i的最终值 6

    let 是块级定义域

    1

    2

    3

    4

    5

    <code>for (let i = 1; i <= 5; i++) {

            setTimeout(function timer() {

                console.log(i);

            }, i * 1000);

        }</code>

    回复
    0
  • 为情所困

    为情所困2017-05-19 10:49:29

    setTimeout有2个特性,它的this与上下文的this分离,它的调用是异步的。

    这里就是【异步】造成的,for循环会先全部完成,再执行setTimeout,因为for循环每次执行到最后都是6了- -所以自然setTimeout再调用i就是五个6

    解决方法一:

    1

    <code>var 换 let</code>

    解决方法二:

    1

    <code>楼主自己用的闭包</code>

    解决方法三:

    1

    2

    3

    4

    5

    6

    <code>//类似于方法二,使用setTimeout的第三个参数直接传参

      for (var i = 1; i <= 5; i++) {

        setTimeout(function(i) {

          console.log(i);

        }, i * 1000,i);

      }</code>

    回复
    0
  • 取消回复