当setTimeout遇到闭包
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作为参数传入闭包,就不会对变量造成污染。