闭包

  闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的常见方式就是在个函数内部创建另一个函数。在一个函数内部定义的函数将包含函数(即外部函数)的活动对象添加到它的作用链中,这样通过内部函数可以访问外部函数的局部变量。通过闭包可以突破作用域链,将函数内部的变量和方法传递到外部。


  在内部函数被返回后,它的作用域链被初始化为外部函数的活动对象和全局变量的对象。这样,内部函数就可以访问在外部函数中定义的变量。更重要的是,外部函数在执行完毕后,其活动对象也不会被销毁,因为内部函数的作用域仍然在引用这个活动对象,即他的活动对象仍然会留在内存中,直到内部函数被销毁后,外部函数的活动对象才会被销毁。



注意: 闭包只能取得包含函数中任何变量的最后一个值闭包所保存的是整个变量对象,而不是某个特殊的变量。

   for(var i = 0; i < 5; i++){
        setTimeout(function(){
            console.log(new Date(),i, 'B'); 
        },1000);
    }
    console.log(new Date(),i,'A');

代码运行结果为:

Thu Aug 10 2017 20:14:28 GMT+0800 (中国标准时间) 5 "A"
Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"
Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"
Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"
Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"
Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"

  表面上看,B处应该输出0、1、2、3、4,即每次调用内部函数时,i 的取值,但实际上,每个函数都返回的是5。因为每次调用setTimeout函数它们引用的都是同一个变量 i 。当for执行完后,变量 i 的值是5,此时每个函数都引用着保存变量 i 的同一个变量对象,所以每个函数内部 i 的取值都是5.



若想在B处输出0、1、2、3、4,则通过需要创建另一个匿名函数强制让闭包的行为符合预期,如下所示:

   for(var i = 0; i < 5; i++){
        (function(num){
            setTimeout(function(){
                console.log(new Date(),num, 'B');   
            },1000);
        })(i)

    }
    console.log(new Date(),i,'A');

代码运行结果为:

Thu Aug 10 2017 20:29:09 GMT+0800 (中国标准时间) 5 "A"
Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 0 "B"
Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 1 "B"
Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 2 "B"
Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 3 "B"
Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 4 "B"

可以注意到A先输出,大约等待1s后,5个B几乎同时输出。

还可以使用 let 修改 for 循环中的变量定义,使 B 处达到预期结果。代码修改见 ES6 —(let、const)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值