当setTimeout遇到闭包

时间:2024-10-30 19:36:08

1:

function myTest(){
for(var i=0; i< 5; i++){
setTimeout(console.log(i), 0);
}
}
myTest();

或者比较正规的写法(code 加上引号):

function myTest(){
for(var i=0; i< 5; i++){
setTimeout("console.log(" + i + ")", 0);
}
}
myTest();

控制台输出结果为 0,1,2,3,4

2:

function myTest(){
for(var i=0; i< 5; i++){
setTimeout(function(){
console.log(i);
}, 0);
}
}
myTest();

控制台输出结果为 5,5,5,5,5

虽然setTimeout(code, 0)为立即执行,但由于javascript为单线程,所以还需等待循环结束后才会执行setTimeout

由于阻塞,在循环中产生的setTimeout事件会被放在执行队列中进行等待。

1中放入执行队列的是:console.log(i) ,结果为 0,1,2,3,4

2中放入执行队列的是:function(){ console.log(i); }, 结果为 5,5,5,5,5 为什么呢

原因:2放入队列的是匿名函数,等到匿名函数执行的时候,变量i已经累加到5了

有时,需要执行的代码不仅仅一句console.log(i)这么简单,那么2中要怎么才能做到输出 0,1,2,3,4

这里就讲到闭包:

内部函数可以使用外部的变量。

既然i为外部变量已经不可控,那就对i下手吧

修改如下:

function myTest(){
for(var i=0; i< 5; i++){
(function(v){
setTimeout(function(){
console.log(v)
}, 1000);
})(i); }
}
myTest();

每次循环先把立即(function(v){...})(i);把i作为参数传入闭包,就不会对变量造成污染。