# 闭包

# 什么是闭包 解决了什么问题

谈闭包 先要谈作用域

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

一个函数执行完成以后 在某个时间 另外一个函数执行会用到第一个函数内部的作用域变量 这就是闭包

只要使用了回调函数,实际上就是在使用闭包! 因为回调的作用就是等待被触发 触发就会使用当时函数作用域

# 循环和闭包

for (var i = 1; i <= 5; i++) {
  setTimeout(function () {
    console.log(i)
  }, i * 1000)
}

缺陷是我们试图假设循环中的每个迭代在运行时都会给自己“捕获”一个 i 的副本。但是根据作用域的工作原理,实际情况是尽管循环中的五个函数是在各个迭代中分别定义的,但是它们都被封闭在一个共享的全局作用域中,因此实际上只有一个 i。

立即执行函数会自己形成一个词法作用域

https://weread.qq.com/web/reader/8c632230715c01a18c683d8ke3632bd0222e369853df322

# 模块(闭包的应用)

如果要更简单的描述,模块模式需要具备两个必要条件。

  1. 必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)
  2. 封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态。

TIP

回调 和 模块 是 闭包的两大模式

# 动态作用域

主要区别:词法作用域是在写代码或者说定义时确定的,而动态作用域是在运行时确定的。(this 也是!)词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用。

词法作用域 静态作用域 书写的时候就确定了变量的一个查找方式

this 动态 需要按照运行时候调用的情况去分别找到上下文

function foo() {
  const a = 12
  return function bar() {
    console.log(a)
  }
}

const bar = foo()

理解为一个背了个背包一个函数(foo)被调用,返回了另一个函数时(bar)这个函数(bar)作用域存在 foo 的变量对象 导致能在非 foo 的执行上下文中访问 a 这个变量

# 闭包/内存泄漏

# 参考文章