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

 

posted @ 2014-10-19 21:46  rubekid  阅读(455)  评论(0编辑  收藏  举报