作用域链按函数定义时的嵌套结构从内到外逐级向上查找变量,路径在函数创建时固化于[[Environment]]中;未声明变量直接报ReferenceError,闭包是其自然结果。

JavaScript 作用域链在变量未找到时向外逐级搜索,本质是按函数定义时的嵌套结构,从内到外、一层不跳地向上回溯。它不看函数在哪调用,只看函数在哪写——这个路径在函数创建时就已固化在 [[Environment]] 中。
查找起点:先查当前词法环境
引擎访问一个变量时,第一步永远是检查当前执行上下文的词法环境(比如函数体内的 let/const 声明,或 var 对应的活动对象)。如果变量存在且已初始化(let/const 已过 TDZ,var 已提升),直接使用;否则进入下一步。
向上一层:严格沿定义嵌套路径推进
没找到就去“父级词法环境”找,这个“父级”由代码书写时的嵌套关系决定:
- 函数内部定义的函数,其父级就是该外层函数的作用域
- if 或 for 块中用
let声明的变量,其父级是所在函数或全局作用域 - 全局作用域没有上一级,它是搜索终点
注意:不会跨分支查找(比如两个并列的 if 块互不可见),也不会因函数被传到别处执行而改变路径。
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
立即学习“Java免费学习笔记(深入)”;
未声明变量直接报错,不是返回 undefined
整个查找过程一旦抵达全局作用域仍未匹配到变量名,引擎立即抛出 ReferenceError: xxx is not defined。这和 typeof undeclaredVar 返回 "undefined" 不同——后者是特殊语法处理,常规读取未声明变量不走作用域链兜底,而是直接失败。
闭包就是作用域链的自然结果
当一个内部函数被返回或传出,它携带的 [[Environment]] 仍指向定义时的外层环境。即使外层函数执行结束、活动对象本该销毁,只要内部函数还活着,那条链上的变量就继续可访问。这不是引擎“记住”了什么,而是链本身在函数创建那一刻就已静态绑定。

















