【JS进阶】JS中的闭包

闭包

1.JS中的垃圾回收机制(GC)

函数中的局部变量会经历一个生命周期:

  1. 当我们定义一个变量时,会为它分配一个内存空间用来储存变量的值;
  2. 当我们读取或使用这个变量时,会使用它的内存空间
  3. 使用完毕时会释放内存空间

上面生命周期的最后一步,其实就是垃圾回收。而 JS 中存在自动的垃圾回收机制,即GC

在 JS 中,如果一个对象不再被引用,那么这个对象就会被 GC 回收。

如果两个对象互相引用,而不再被第三者所引用,那么这两个互相引用的对象也会被回收。

通常对于某个变量,我们不需要使用之后,就可以把它的值设置为 null ,这样垃圾回收器就会回收这个变量占用的空间了!

一般来说,当一个函数执行完毕,那么这个局部作用域内的变量就没有存在的必要了,它的内存空间就会释放

但是实际上有一种情况可以阻止这一进程,那就是 — 闭包

2.闭包的概念

当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行

看下面这个例子:

function foo() {
    var a = 2;
    
    // 函数bar() 的词法作用域能够访问foo() 的内部作用域。
    function bar() {
        console.log( a );
    }
    return bar;
}

var baz = foo();
baz(); // 2 —— 朋友,这就是闭包的效果。

// 在foo() 执行后,其返回值(也就是内部的bar() 函数)赋值给变量baz并调用baz()
// 实际上只是通过不同的标识符引用调用了内部的函数bar()。
// bar() 显然可以被正常执行,而且是在自己定义的词法作用域以外的地方执行了。

以上代码中,在foo() 执行后,通常会期待foo()的整个内部作用域都被销毁,因为我们知道引擎有垃圾回收器用来释放不再使用的内存空间。由于看上去foo()的内容不会再被使用,所以很自然地会考虑对其进行回收。

闭包的“神奇”之处正是可以阻止这件事情的发生。事实上内部作用域依然存在,因此没有被回收。谁在使用这个内部作用域?原来是bar() 本身在使用

bar() 所声明的位置所赐,它拥有涵盖foo()内部作用域的闭包,使得该作用域能够一直存活,以供bar() 在之后任何时间进行引用。bar() 依然持有对该作用域的引用,而这个引用就叫作闭包

即:

  1. 函数在定义时的词法作用域以外的地方被调用时,闭包使得函数可以继续访问定义时的词法作用域。
  2. 无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。

3.闭包的特性和应用场景

3.1 闭包的特性
  • 被闭包函数访问的父级及以上的函数的局部变量(如范例中的局部变量 i )会一直存在于内存中,不会被JS的垃圾回收机制回收,即数据持久性
  • 闭包函数实现了对其他函数内部变量的访问。(函数内部的变量对外是无法访问的,闭包通过这种变通的方法,实现了访问。)
3.2 闭包的应用场景
  • 模拟面向对象的代码风格 - 属性 + 方法
  • 使 setTimeOut 方法支持传参
  • 封装私有变量 - 闭包可以⽤来创建私有变量,还可以延⻓变量的⽣命周期。⽐如在函数内定义变量,然后get和set⽅法,这样在函数外部就可以通过get、set访问到内部的变量,就实现了一个私有变量。
  • 模拟块作用域
  • 实现迭代器
3.3 闭包的优缺点

优点:

  1. 可以减少全局变量的定义,避免全局变量的污染
  2. 能够读取函数内部的变量
  3. 在内存中维护一个变量,可以用做缓存

缺点:

  • 造成内存泄露
    1. 闭包会使函数中的变量一直保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
    2. 解决方法 - 使用完变量后,手动将它赋值为null;
  • 闭包可能在父函数外部,改变父函数内部变量的值
  • 造成性能损失
    1. 由于闭包涉及跨作用域的访问,所以会导致性能损失。
    2. 解决方法 - 通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响

4.循环与闭包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值