关于settimeout的面试题

废话不多说,先上代码

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

毫无疑问,结果为0,1,2,3,4

再看下面的情况

1 for( var i = 0;i<5;i++) {
2     setTimeout(function() {
3         console.log(i);
4     },1000)
5 }

此时,结果为5,5,5,5,5

for循环会先执行完(同步优先于异步优先于回调)

上面代码中settimeout在for循环里是异步执行的,在延迟输出的时候,i的值已经是5了,因此输出5,5,5,5,5

若要实现每隔一秒输出i,该怎么改呢???

方法一:利用自执行匿名函数

1 for (var i = 0; i < 5; i++) { 
2   (function(i){   //立刻执行函数
3     setTimeout(function (){
4       console.log(i); 
5      },1000); 
6   })(i); 
7 }

这里利用了自执行匿名函数,这样console.log(i);中的i就保存在每一次循环生成的自执行匿名函数中的作用域中了。

方法二:利用let

1 for (let i = 0; i < 5; i++) {   //let 代替 var
2   setTimeout(function (){
3     console.log(i); 
4    },1000); 
5 }

ES6中let声明的变量具有块级作用域,所以每次for循环,console.log(i);都引用for代码作用域下的i,因为这样被引用,所以for循环结束后,这些作用域在settimeout伪执行前都不会被释放

 
原文地址:https://www.cnblogs.com/endlessmy/p/8652668.html