循环中的闭包

经典例子:(http://bonsaiden.github.io/JavaScript-Garden/zh/#function.closures

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);  
    }, 1000);
}
不过这段代码执行的结果是10,而不是0,1,2,3,4,5,6,7,8,9。

为什么呢?

(引自:http://www.douban.com/note/293295975/

因为setTimeout是异步的!
   你可以想象由于setTimeout是异步的, 因此我们将这个for循环拆成2个部分
   第一个部分专门处理 i 值的变化, 第二个部分专门来做setTimeout
   因此我们可以得到如下代码
   // 第一个部分
   i++;
   ...
   i++; // 总共做10次

   // 第二个部分
   setTimeout(function() {
      console.log(i);
   }, 1000);
   ...
   setTimeout(function() {
      console.log(i);
   }, 1000); // 总共做10次

   这样一拆后, 我相信你肯定知道之前那个for循环的运行结果了.
   由于循环中的变量 i 一直在变, 最终会变成10, 而循环每每执行setTimeout时, 其中的方法还没有真正运行, 等真正到时间执行时, i 的值已经变成 10 了!
   i 变化的整个过程是瞬间完成的, 总之比你异步要快, 就算你setTimout是0毫秒也一样, 会先于你执行完成.

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

避免引用错误

为了正确的获得循环序号,最好使用 匿名包裹器译者注其实就是我们通常说的自执行匿名函数)。

for(var i = 0; i < 10; i++) {
    (function(e) {
        setTimeout(function() {
            console.log(e);  
        }, 1000);
    })(i);
}

外部的匿名函数会立即执行,并把 i 作为它的参数,此时函数内 e 变量就拥有了 i 的一个拷贝。

当传递给 setTimeout 的匿名函数执行时,它就拥有了对 e 的引用,而这个值是不会被循环改变的。

有另一个方法完成同样的工作;那就是从匿名包装器中返回一个函数。这和上面的代码效果一样。

for(var i = 0; i < 10; i++) {
    setTimeout((function(e) {
        return function() {
            console.log(e);
        }
    })(i), 1000)
}
以上引自(密码花园: http://bonsaiden.github.io/JavaScript-Garden/zh/#function.closures

上面的代码看起来都比较费劲,下面我把代码拆分开,更容易理解一些。

window.οnlοad= function(){
for(var i=0; i<5; i++){
/*(function(j){
setTimeout(function(){  //setTimeout是在循环结束后才被“异步”调用的
console.log(j+'');
},100);
})(i);*/
            test(i);
}
}
function test(j){
setTimeout(function(){
console.log(j+'');
},100);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值