关于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伪执行前都不会被释放