js闭包和for循环

以下解释均为个人理解,有错误之处的话欢迎提出,能给出建议的话万分感激!


在闭包中,for循环是一个经典实例。
例1:
for(var i=1;i<=5;i++){
  setTimeout(function timer(){
    document.write(i);
  },1000);
}
//输出5个6
解释:本意是想通过循环输出12345,但是因为js中for循环没有块级作用域,即迭代产生的i都在全局作用域里,每次迭代后i被改变,而延迟函数的回调会在for循环结束后执行(该知识为异步执行(我还未学习。。),可见http://cnodejs.org/topic/5401dfb79769c2e93756216b),即五个延迟函数在循环结束后执行,因为闭包的原因,延迟函数获取全局的i(即i=6),所以输出5个6


例2:

IIFE是指(function foo(){....})()的模式


for(var i=1;i<=5;i++){
  (function (){
    setTimeout(function timer(){
      document.write(i);
    },1000);
  })();
}
//输出5个6
解释:虽然使用了IIFE(但IIFE是空的,即只有延迟函数),但是每次执行的延迟函数因为闭包的原理,还是从全局获取i,所以仍然输出5个6


例3:
for(var i=1;i<=5;i++){
  (function (j){
    setTimeout(function timer(){
      document.write(j);
    },1000);
  })(i);
}
//输出12345
for(var i=1;i<=5;i++){
  (function (){
    var j=i;
    setTimeout(function timer(){
      document.write(j);
    },1000);
  })();
}
//输出12345


解释:例3和例4原理一样。因为IIFE中传入参数,即IIFE中有定义变量j;因为IIEF每次都会创建一个作用域,j在该作用域保存着每次迭代的i的值,而延迟函数会将IIEF每次创建的作用域封闭起来(即闭包),然后延迟函数等循环结束后执行,通过闭包,执行延迟函数时记得并能访问每次迭代的作用域。


例5:
for(var i=1;i<=5;i++){
  let j=i;
  setTimeout(function timer(){
    document.write(j);
  },1000);
}
//输出12345
for(var i=1;i<=5;i++){
  var j=i;
  setTimeout(function timer(){
    document.write(j);
  },1000);
}
//输出5个5
解释:let的使用,劫持形成块级作用域,为什么要用块级作用域呢?就如同例3例4的IIEF的函数作用域一样。详细原理同上。注:例5的let的使用会使j声明5次


for(let i=1;i<=5;i++){
  setTimeout(function timer(){
    document.write(i);
  },1000);
}
//输出12345
解释:由于let的使用,形成块级作用域,而且由于对i使用let声明,所以就相当于使该for循环变成块级作用域,且只需要声明一次。


对上述的作用域和延迟函数的‘纠缠’:
我理解为,当直接使用for循环时,因为闭包,相当于执行5次在for循环外的延迟函数
使用IIFE和let时,循环结束后执行延迟函数,通过延迟函数的闭包,能访问其函数(或块)级作用域(因为闭包的原因保留着),所以可以输出每次迭代的值。




  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值