1. 闭包的定义

闭包是指有权访问另一个函数作用域中的变量的函数.

2. 闭包的常见表现形式

  1. 在函数中返回一个函数
  2. 立即调用匿名函数(IIFE)

3. 闭包涉及的特性

3.1 垃圾回收机制

JavaScript 的垃圾回收机制是自动回收, 回收的标准是只要一个变量在内存中还存在着引用, 那么该变量就不会被垃圾回收机制回收, 会一直存在于内存中.
这个是闭包存在的前提.

3.2 作用域

JavaScript中, 作用域有4种, 大括号作用域, for 循环括号作用域, 函数作用域, 全局作用域

  1. 大括号作用域
  2. for 循环括号作用域
  3. 函数作用域
  4. 全局作用域

这里特别说一下for 循环括号作用域: for 循环中的括号存在着一个单独的作用域, 如下代码所示

for (let i = 0; i < 5; i++) {
    let i = 'here'
    console.log(i)
}
// here
// here
// here
// here
// here

3.3 作用链域

作用链域是JavaScript 变量的访问机制, 它表示当访问一个变量时, 我们会现在当前作用域寻找, 如果没有找到相对应的变量, 那么根据作用链域的嵌套依次向上寻找, 直到全局作用域

4. 闭包理解

只要内存中存在着函数中变量的引用, 那么该函数就会一直存在于内中,不会被垃圾回收机制清理, 而且该函数的变量能够在作用链域的作用下被访问到

5. 闭包优势和局限

5.1 优势

  1. 消除全局变量
  2. 使变量存在于内存中, 使其能被访问到, 同时保存还可以保存对变量操作的结果

5.2 闭包造成的问题

  1. 由于闭包会使函数一直存在于内存中, 可能造成内存泄漏

6. demo

function counter(number=0) {
    let result = number
    function caculate() {
        result++
        return result
    }
    return caculate
}

let a = counter(10)
let b = counter()
a() // 11
a() // 12
b() // 1

7. 参考链接

  1. MDN文档
  2. 阮一峰老师关于闭包的博客