Skip to content

闭包

什么是闭包

闭包

定义:

函数嵌套,内部函数总是能够记录访问外部函数的函数作用域里的变量的一种特性

条件:

  1. 函数嵌套,外部函数,内部函数
  2. 内部函数引用了外部函数的变量
  3. 内部函数被保留(返回、传入、或赋值给全局变量)

词法环境

每个函数被调用或代码块执行时,都会创建对应的执行上下文,其中包含一个词法环境。词法环境用于记录当前作用域内的所有变量、函数声明,以及对外部词法环境的引用。当代码块执行完成且内部函数未被外部引用时,词法环境会被垃圾回收。

词法环境的核心作用是维护作用域链:它记录当前作用域的所有变量,同时保存对外部词法环境的引用。查找变量时,先在当前词法环境中查找,找不到则沿外部词法环境逐级向上查找,直至全局词法环境。这种链式查找机制称为作用域链。

全局环境就是全局词法环境。

当内部函数被外部保留时(如作为返回值、参数传递或赋值给全局变量),其词法环境会被保留,即使外部函数已执行完毕。这就是闭包能够持续访问外部函数变量的根本原因。

闭包优缺点

优点说明
变量私有化创建无法被外部直接访问的私有变量
避免全局污染变量存在函数内部,不会挂载到 window
变量持久化变量在函数执行结束后依然存活
状态保持多次调用同一函数,能记住之前的状态
函数工厂动态生成定制化的函数
模块化实现命名空间和代码隔离
js
function createCounter() {
  let count = 0

  return {
    increment: () => ++count,
    decrement: () => --count,
    getCount: () => count
  }
}

防抖

状态保持

js
function debounce(fn, delay) {
  let timer = null

  return function (...args) {
    if (timer) clearTimeout(timer)

    timer = setTimeout(() => fn.apply(this, args), delay)
  }
}

节流

状态保持

js
function throttle(fn, delay) {
  let lastTime = 0

  return function (...args) {
    const now = Date.now()

    if (now - lastTime >= delay) {
      lastTime = now

      fn.apply(this, args)
    }
  }
}