← [ BACK_TO_NOTES ]

ECMAScript闭包

闭包是函数与其词法环境绑定后形成的可访问组合。

#concept #growing #javascript #ecmascript

[!info] related notes

ECMAScript闭包

闭包可以先记成一句话:函数把定义时可访问的词法环境一起带走了。

最短定义

  • 闭包不是单独一种语法,而是函数和其外层词法环境的组合
  • 只要函数在别处执行时,仍然能访问定义位置的变量,就已经进入闭包语境
  • 最常见形式是函数返回函数,但回调、事件处理器、模块工厂也都会产生闭包

它为什么成立

  • ECMAScript 使用词法作用域,变量可访问性由定义位置决定
  • 函数是一等对象,可以被返回、传递、保存
  • 只要内部函数还被引用,相关词法环境就可能继续存活

它主要解决什么

  • 保留跨调用的私有状态
  • 给回调保留创建时的上下文
  • 构造函数工厂、模块封装、柯里化等模式都依赖这种能力

最容易误解的点

  • 闭包不等于内存泄漏;问题在于不再需要的引用没有释放
  • 闭包捕获的是变量绑定,不一定是当时的值快照
  • 只背“return 一个内部函数”不够,重点是词法环境没有丢

一个最小例子

function makeCounter() {
  let count = 0;

  return function () {
    count += 1;
    return count;
  };
}

const next = makeCounter();

next(); // 1
next(); // 2

makeCounter() 已经执行结束,但返回的函数仍然能访问 count,这就是闭包最典型的表现。

这篇和相邻笔记怎么分工

与柯里化的关系

柯里化 经常利用闭包保存已经接收的参数,但“闭包”是语言机制,“柯里化”是建立在函数和闭包之上的函数变换模式。

本页只维护闭包本体;柯里化的定义、实现与部分应用边界统一放在 柯里化。

学习检查

不看正文回答:

  1. 闭包为什么不是“函数里面再写一个函数”的语法现象?
  2. 词法环境与函数定义位置如何决定闭包能访问哪些绑定?
  3. 为什么闭包捕获的是变量绑定,而不一定是创建时的值快照?
  4. 函数已经离开原始调用栈后,为什么仍可能访问外层变量?
  5. 闭包为什么可能延长对象生命周期,但又不能等同于内存泄漏?
  6. 防抖、事件回调、私有状态、柯里化分别怎样利用闭包?
  7. 给一个循环 + 异步回调案例,闭卷预测输出,并解释捕获绑定发生了什么。
创建于 2025/1/1 更新于 2026/9/30
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本