For循环+setTimeout中那些趣事

jeckson

共 1159字,需浏览 3分钟

 · 2021-03-30

13d9dc4d8a65bede1a8a88472e40205f.webp

今天面试再次遇到for+setTimeout问题。再次仔细品尝了一下,也算获取更多一点知识,接下来,我们把它完全搞清楚。

17976b92135f8857c1065e7e842b1972.webp

第一个例子

17976b92135f8857c1065e7e842b1972.webp
for(var i=0;i<10;i++){   setTimeout(console.log(i),1000);//0-10}

这个可能很多人一上来会说应该打印10个10,其实不是,是0-9.为什么呢,因为console.log()是立即执行函数也就是IIFE,而console.log只是一个function 函数名。所以console.log()是同步任务跟for循环是同步执行的,而setTimeout()是异步任务需要等到主线程的同步任务执行完毕后才能执行,所以结果就是0、1、2、3、4、5、6、7、8、9了。

第二个例子

17976b92135f8857c1065e7e842b1972.webp
for(var i=0;i<10;i++){   setTimeout(()=>{      console.log(i)   },1000);//10个10}

这个应该都熟悉,打印10个10,因为setTimeout是异步函数,加上打印的是外面的变量,因为使用var 声明变量i。相当于下面这样,等队列任务处理完,轮到打印的时候,i已经是10啦。

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

第三个例子

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

这个稍微不一样,原因是有了闭包,很多同志还不清楚闭包到底是什么。一句话就是:在一个嵌套函数中,函数内部可以引用外部的参数和变量,并且不被GC回收,也就是函数内部被其它引用了。

第四个例子

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

这个没有什么说的用了let,每次循环会有单独的作用域。


春生万物生

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

这个又是为什么呢,仔细一看,就和第一个一样的,只是视野混淆了。也是IIFE。

17976b92135f8857c1065e7e842b1972.webp

总结

1、IIFE、闭包一类都是解决它最后打印的是它循环的最后一个值。

17976b92135f8857c1065e7e842b1972.webp


浏览 54
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报