Skip to content

闭包

闭包是一种机制,代码只是具体的表现形式,例如我们常说的大函数嵌套小函数,再返回一个小函数 函数执行时会生成一个新的执行上下文,一般来说函数中的代码执行结束之后就需要出栈从而释放当前上下文所占据的内存空间,从而释放它内部的声明和值,但是如果当前执行上下文当中的数据(一般就是堆内存引用)被当前上下文之外的变量所引用,那么这个上下文就不能被释放,此时就形成了一个闭包

闭包的好处就是可以对一些数据进行保存,例如下文中的 zz ,函数内部的 zz 和全局的 zz 互不干扰,同时闭包可以保存数据,例如 0x001 所对应的内存空间,本该在 FN 执行结束之后释放掉,但是由于 EC(G) 当中的 foo 对其有引用,所以让它可以在后续的代码中继续被使用

js
var zz = 100
function fn() {
  var zz = 200
  return function (a) {
    console.log(a + zz++)
  }
}

var foo = fn()
foo(10)
foo(20)

闭包与垃圾回收

  • 上述代码运行可以发现,代码的运行是需要内存空间的,无论是栈内存还是堆内存都属计算机内存
  • 内存空间的大小是有上限的,因此不能无限制使用,所以需要内存管理,也就是垃圾回收
  • 以chrome 为例,它会在空间时间执行垃圾回收操作,完成内存空间的回收
    • 栈内存
      • 主要用于存储基本数据类型值
      • 当某一个上下文执行结束之后,如果它内部的空间没有再被其它人使用,那么就会释放掉这部分空间完成回收
    • 堆内存
      • 用于存放引用数据类型
      • 如果A上下文中的堆内存在 A 中代码执行完成之后,仍然被B上下文所引用,那么这个堆内存及A上下文所占用的空间就无法被释放掉,也就是常说的闭包,如果这样的代码多了那么对于性能也就是一种消耗
    • 在合适的地方主动的将变量定义为 null,释放掉某些引用
    • EC(G):全局执行上下文是在浏览器加载界面的时候就创建的,因此界面如果不关闭,这部分执行上下文也是不会被回收的

js
let m = 5
function foo(m) {
  return function (n) {
    console.log(n + (++m))
  }
}

let fn = foo(8)
fn(10)
foo(11)(13)
fn(20)
console.log(m)
---------------------------------------
function fun(n, o) {
  console.log(o)
  return {
    fun: function (m) {
      return fun(m, n)
    }
  }
}
var c = fun(10).fun(3)
c.fun(6)
c.fun(8)

Released under the MIT License.