词法作用域是闭包形成的底层前提——函数在定义时静态捕获外层变量,通过[[environment]]属性持久保存,使内层函数即使在外层执行完毕后仍能访问其词法环境。

词法作用域是闭包形成的底层前提——没有它,闭包就不可能存在。JavaScript 在函数定义那一刻,就静态地记录下它所处的词法环境(即外层作用域中的变量、参数等),这个“快照”被绑定到函数内部,成为其永久的一部分。
词法作用域决定函数“记住什么”
函数不是在调用时才查找变量,而是在定义时就锁定了能访问哪些标识符。闭包之所以能访问外部变量,正是因为引擎依据词法位置,把外层作用域链保存进了函数的 [[Environment]] 内部属性中。
- 哪怕 outer 函数执行完毕、执行上下文被销毁,inner 函数仍能通过 [[Environment]] 找到当初定义它时的 outer 变量
- 这种绑定发生在代码写完、解析完成的阶段,与运行时调用位置无关
- 如果 JavaScript 是动态作用域(比如按调用栈查找),inner 就会去查 谁调用了它 的作用域,而不是 它写在哪 的作用域——那样闭包就失效了
闭包本质就是词法作用域的“携带能力”
闭包不是特殊语法或新对象,而是函数天然具备的词法行为结果:一个函数 + 它定义时捕获的词法环境。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- function makeAdder(x) { return function(y) { return x + y; }; } —— inner 函数在定义时就捕获了 x,x 不是传参得来,而是从词法上“就近”抓取的
- 每次调用 makeAdder(5) 和 makeAdder(10),生成的两个 inner 函数各自持有不同 x 的词法快照,互不干扰
- 这种隔离和持久化,完全依赖于词法作用域的静态性
没有词法作用域,闭包就退化为普通嵌套
若作用域由调用时决定(动态作用域),下面代码的行为将完全不同:
- 当前行为:greetJohn() 输出 "Hello, John",因为 sayHello 记住的是 greet('John') 定义时的 name
- 动态作用域下:sayHello 若在全局调用,就会去全局找 name,报错或取到错误值
- 真实情况中,正是词法作用域让“返回函数 + 保留状态”这一模式变得可靠且可预测
实际开发中要靠词法结构来设计闭包
你无法靠运行时逻辑“触发”闭包,只能靠代码的嵌套层级和变量声明位置来构造它:
- 必须有外层函数声明变量/参数
- 必须有内层函数在词法上处于该外层函数内部
- 内层函数必须引用外层的变量(哪怕只读)
- 外层函数必须返回内层函数(或以其他方式将其暴露到外层作用域)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










