闭包

闭包其实我们经常会在代码中遇到,只是我们可能没有发现而已,我们经常用到的Ajax请求,定时器,事件监听器,跨窗口通信,以及其它的异步(或同步)任务中,只要使用了回调函数,实际上就是使用了闭包。

首先在了解闭包之前,我们先要了解几个概念,作用域和执行上下文以及作用域链

作用域链

JS中所有的函数都有它的执行环境,当它执行的时候会将当前环境压入环境栈中,如果执行完毕,会将当前环境弹出,每个执行环境中都有它对应的变量对象,里面保存着函数作用域中定义的变量和还有其他的信息,作用域链最顶端是当前执行环境的变量对象,下一个是上一层的变量对象,一直到最顶端window对象。

作用域
js中作用域包括全局作用域和函数作用域
执行上下文

执行上下文即当前代码的执行环境
执行上下文可以描述成式一个包含变量对象(对应全局)/活动对象(对应函数)、作用域链和 this 的数据结构。

闭包

一般为函数嵌套函数的形式,内层函数可以访问到外层函数的变量,外层函数的变量访问不到内层函数的变量,外层变量对象在内层的作用域链上

存在的问题:外面的函数执行完毕后里面的变量对象仍旧存在,容易导致内存泄漏

实例代码:

function f1(){
 var n=99;
 function f2(){
    alert(n);
 }
}
var result=f1();
result();

代码的弹出结果为99

其中的f1()就是一个闭包函数

闭包的使用场景

  • 模拟块级作用域
  • 模块化开发
    模块化开发的特点:必须有外部的封装函数,该函数至少被调用一次,封闭函数必须返回一个内部函数。
    模块化开发的优点:灵活,多人写协作互不干扰,可维护性好

举个例子:

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

你觉得输出结果会是什么呢?
间隔为1秒,相继输出0,1,2,3,4,5

答案是不对
正确的输出结果应该是间隔为1秒,相继输出5个6

原因:因为变量i是在全局作用域中共享的,setTimeout中的代码每执行一次都会创建一个闭包,这样就创建了6次闭包,但是因为代码真正执行输出的时候,i已经是循环退出条件6了,所以输出结果是6个6

更改后的代码:

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

这样代码的运行结果就和想象中的一样了,其实还有一种办法

for(let i=0;i<=5;i++)
    {
            setTimeout(function () {
                console.log(i);
            },i*1000);
    }

这样也可以的原因是let会劫持作用域,并在这个块作用域上声明一个变量,后者应该比较酷炫吧

那么怎么解决闭包引起的内存泄漏问题呢?

在函数结束之前给闭包中使用的变量赋值为null,以便后期垃圾收集器回收内存。

JS的垃圾回收机制

JS的垃圾回收机制分为两种,分别为标记清除和引用计数

标记清除:垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,然后它会去掉环境中的变量以及环境中的变量引用的变量的标记,如果此时还存在有标记的变量就视为准备删除的变量,因为环境中的变量无法访问到这些变量,最后垃圾收集器完成内存清理,销毁这些变量并回收内存。

引用计数:记录每一个值被引用的次数,当声明一个变量并将一个引用类型值赋给该变量时,该变量的引用次数加一,如果一个值又被赋给另外一个变量,则该值的引用次数减一,当这个值的引用次数为0时,就说明没有办法再访问这个值了,就可以回收该变量的空间,当垃圾收集器下次运行时,它会释放这个值占用的内存。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值