闭包的本质

29 阅读1分钟

闭包的本质

  1. js 是词法有作用域语言
  2. 基于标记清除法的垃圾回收机制

词法作用域(源码作用域)

Dart 和 js 都是词法有作用域语言,变量的作用域在写代码的时候就确定了,大括号内定义的变量只能在大括号内访问

词法闭包

函数能够访问到的变量在它定义(书写)的时候就已经确定了

function makeAdder(addBy) {
    return i => addBy + i;
}

(function () {
    let add2 = makeAdder(2);

    // Create a function that adds 4.
    let add4 = makeAdder(4);

    // 闭包
    console.log(add2(3))
    console.log(add4(3))
})()

// 5
// 7

函数 add2add4 在书写的时候是可以访问到变量 addBy 的,而后续函数 add2add4 可能会用到这个变量,因此在函数 makeAdder 执行完成后,变量 addBy 并没有被销毁

以上的特性就是闭包(词法闭包)

很明显,利用闭包可以在内存中维护一个状态变量

基于标记清除法的垃圾回收机制

比如下面的代码:

当退出函数后,局部变量 a 并没有消失,而是似乎一直在某个地方存活着。这是因为当执行var f = func();时,f 返回了一个匿名函数的引用,它可以访问到 func() 被调用时产生的环境,而局部变量 a 一直处在这个环境里。既然局部变量所在的环境还能被外界访问,也就是说基于标记清除法的垃圾回收机制不会回收这个局部变量。在这里产生了一个闭包结构,局部变量的生命看起来被延续了