资讯专栏INFORMATION COLUMN

for循环与setTimeout

XGBCCC / 979人阅读

摘要:修改下面代码,使其能够正确运行为什么上面代码的执行结果是首先说明,这与异步和作用域都有关系。先来说和异步的关系,是异步操作,所谓的异步就是会在同步操作全部执行完成之后,才开始执行的。

// 修改下面代码,使其能够正确运行
for(var i = 0; i < 6; i++) {
    setTimeout(function timer(){
        console.log(i)
    }, i * 1000)
}

为什么上面代码的执行结果是 [6,6,6,6,6,6] ?
首先说明,这与异步和作用域都有关系。
先来说和异步的关系,setTimeout是异步操作,所谓的异步就是会在同步操作全部执行完成之后,才开始执行的。放在上面的代码中解释就是,setTimeout是在每次for循环的时候都会调用的(用于将setTimeout内部的代码放入队列,在同步代码执行完成之后,再根据定时执行),但是setTimeout中的代码是在for循环结束之后才开始执行的,所以当for循环执行完成的时候,i变成了6,那么timer中对i的引用也变成了6。

然后是和作用域的关系,for循环中定义的变量i ,它的作用域是什么?

for(var i = 0; i<6; i++)   ---->  var i = 0; for(i; i<6; i++)

是 window,所以当for循环执行完成的时候,全局变量i的值为6,此时去执行队列中的timer函数,但是timer中并没有定义i,所以就会沿着作用域链向外层查找,就找到了window中的全局变量i,值为6。

// 第一种方法:使用立即执行函
for(var i = 0; i < 6; i++) {
    (function(j){
        setTimeout(function timer(){
            console.log(j)
        }, j * 1000)
    })(i)
}

// 第二种方法:使用let关键字
for(let i = 0; i < 6; i++) {
    setTimeout(function timer(){
        console.log(i)
    }, i * 1000)
}

这两种方法的本质其实是一样的,都是创建了一个新的变量去保存for循环中每次变化的i的值,再将其传递给timer,使timer每次在执行的时候都能得到正确的值。在使用let的时候,可以看到babel将其转译之后的结果,使用了一个新的参数来保存每次循环时的i,所以在6次循环中,会开辟出6个内存空间,保存着6个不同的i ,这样的话,setTimeout中对i的引用就能得到正确的值。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99503.html

相关文章

  • JavaScript系列——JavaScript同步、异步、回调执行顺序之经典闭包setTimeou

    摘要:同步异步回调傻傻分不清楚。分割线上面主要讲了同步和回调执行顺序的问题,接着我就举一个包含同步异步回调的例子。同步优先回调内部有个,第二个是一个回调回调垫底。异步也,轮到回调的孩子们回调,出来执行了。 同步、异步、回调?傻傻分不清楚。 大家注意了,教大家一道口诀: 同步优先、异步靠边、回调垫底(读起来不顺) 用公式表达就是: 同步 => 异步 => 回调 这口诀有什么用呢?用来对付面试的...

    lewif 评论0 收藏0
  • JavaScript系列——JavaScript同步、异步、回调执行顺序之经典闭包setTimeou

    摘要:同步异步回调傻傻分不清楚。分割线上面主要讲了同步和回调执行顺序的问题,接着我就举一个包含同步异步回调的例子。同步优先回调内部有个,第二个是一个回调回调垫底。异步也,轮到回调的孩子们回调,出来执行了。 同步、异步、回调?傻傻分不清楚。 大家注意了,教大家一道口诀: 同步优先、异步靠边、回调垫底(读起来不顺) 用公式表达就是: 同步 => 异步 => 回调 这口诀有什么用呢?用来对付面试的...

    rockswang 评论0 收藏0
  • 前端校招准备系列--js中的setTimeout到底是什么?

    摘要:浏览器是多进程的,而浏览器的内核渲染进程是多线程的。如果已经将回调函数放进任务队列,但是主线程正在执行一个非常耗时的任务,当这个任务执行完毕后,主线程去任务队列中取任务,这个时候,就会出现连续执行的情况,也就是说相当于失效了。 前言   在刷笔试题的时候,经常会碰到setTimeout的问题,只知道这个是设置定时器;但是考察的重点一般是在一个方法中包含了定时器,定时器中的打印和方法中打...

    Godtoy 评论0 收藏0
  • process.nextTick() 、setTimeout()、setInterval() 运行机

    摘要:注意如果主逻辑的代码执行时间已经超过了第二个参数设置的时间,那么等运行到该回调函数时,它会忽略掉这个时间,并立即执行。如果某一个进行大量的计算,那么它就会阻塞在当前的回调函数中,等待该计算完成后,再执行下一个的回调函数。 setTimeout() ​ JavaScript是一个单线程的语言,也就是说它同一时间只能执行一段代码,接下来我们通过两个例子说明一下单线程语言和多线程语言的...

    lscho 评论0 收藏0

发表评论

0条评论

XGBCCC

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<