setTimeout 与 闭包。。。

先看下面一个比较坑的代码闭包

for (var i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log(i);
    }, i*1000 );
}

首先一个for循环, 会执行五次, setTimeout被执行了五次函数

但里面的timer这时候并无执行, 而是依次在1 2 3 4 5秒后执行spa

此时只创建了全局上下文;code

 

timer放在了事件队列里面执行; timer执行时, for循环已经完成blog

全局做用域中的i变量值变成了6, 此时建立timer的做用域和做用域链队列

 

由于timer里面并无定义i, 也没有给i赋值, 因此timer 在本身的做用域是找不到i的,事件

只能沿着做用域往上找, 找到全局做用域的i, 作用域

timeri 获取全局做用域i, 也就是6, 因此5次timer都是输出6io

 

当加入闭包的时候, 状况就不同了。console

 

for (var i=1; i<=5; i++) {
          
            (function(j) {
                window.setTimeout(function(){console.log(j)}, j*1000);
            })(i)
        }
 

 

第一次 for循环的时候, 同时又有自执行函数

也就是在for执行的同时, 执行了匿名函数, 建立了匿名函数的做用域, 此时创建了匿名函数的上下文环境;

进入匿名函数的做用域的时候, 包含了一个内部函数 function(){console.log(j)}

同时这个函数被全局变量 window.setTimeout引用,这就造成了闭包!

 

在匿名函数执行完后,匿名函数的执行上下文出栈

也就是在for循环第一次执行完后,

匿名函数的的活动变量 j , 因为闭包的关系,并无被销毁,

而是保存在第一个window.setTimeout定时器中, 此时i 是1; j也是1; 这个值会一直保存在第一个定时器属性中;

直到第一个定时器被销毁;

 

而后进入第二次循环, 同理 又进入匿名函数, 建立了第二个闭包, 闭包的活动变量j 被第二个定时器引用;

也会保存在在第二个定时器中, 此时 i,j都是2;

 

依次类推, 3 4 5; 完成需求!

相关文章
相关标签/搜索