作用域链决定变量查找顺序:从当前词法环境开始逐级向上至全局,静态绑定、与调用位置无关;未找到则抛ReferenceError(严格模式),var提升不报错,let/const有TDZ;闭包本质是函数携带定义时的作用域链。

作用域链直接决定变量查找的顺序:从当前执行上下文的词法环境开始,逐级向上,直到全局作用域为止。这个顺序是静态确定的,跟函数在哪调用完全无关。
查找起点是当前词法环境
每次访问变量(比如 x),JS 引擎第一站就是当前执行上下文的词法环境记录(Lexical Environment Record)。这里存着当前作用域里用 let、const、function 或参数声明的标识符。
- 如果找到,立即返回对应值
- 如果没找到,不报错,而是顺着 outer 引用跳到上一级词法环境
向上查找靠 outer 引用串联
每个函数在定义时就固化了自己的 outer 指向——它指向的是其**定义时所处的外层词法环境**,不是调用时的环境。这种静态绑定构成了一条只读链:
- inner() → outer() → 全局
- 哪怕 inner 被作为回调传到别处执行,这条链也不变
- 全局作用域没有 outer,是链的终点
找不到变量会抛出 ReferenceError
引擎沿着作用域链一路查,直到全局也未命中该标识符,就会停止并抛出 ReferenceError(严格模式下);非严格模式下对未声明变量取值会返回 undefined,但这是历史遗留行为,现代代码应避免依赖。
- var 声明会被提升并初始化为 undefined,所以不会报错,但值可能是意外的
- let/const 存在暂时性死区(TDZ):在声明语句前访问,哪怕在同级作用域,也会直接报 ReferenceError
闭包的本质就是保留了这条链
当一个函数被返回或以其他方式脱离其原始定义环境后仍能访问外层变量,正是因为它的执行上下文始终携带着完整的、定义时生成的作用域链。链上的每一级词法环境都可能还持有活跃的变量绑定,这就构成了闭包的内存基础。











