# 闭包

# 闭包的概念

闭包就是能够读取其他函数内部变量的函数,是作用域应用的特殊情况 由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“。 所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

# 闭包的用途

闭包可以用在许多地方。它的最大用处有两个:

  1. 可以读取函数内部的变量

  2. 让这些变量的值始终保持在内存中,不会在调用后被自动清除

# 使用闭包的注意点

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

# 注意

function print(fn) {
    const a = 200
    fn()
}
const a = 100
function fn() {
    console.log(a)
}
print(fn) // 100
1
2
3
4
5
6
7
8
9

所有的自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方!!!

# 总结

实际上闭包只是一个标准,显然就是关于如何在函数作为值按需传递的 词法环境中书写代码的。

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

如果没能认出闭包,也不了解它的工作原理,在使用它的过程中就很容易犯错,比如在循 环中。但同时闭包也是一个非常强大的工具,可以用多种形式来实现模块等模式。 模块有两个主要特征:

  1. 为创建内部作用域而调用了一个包装函数;
  2. 包装函数的返回值必须至少包括一个对内部函数的引用,这样就会创建涵盖整个包装函数内部作用域的闭包。