JavaScript中作用域链向上查找变量是指引擎从当前执行上下文的词法作用域逐级向外层搜索,直至全局作用域;该链在函数定义时确定,由[[Environment]]指针链接各层词法环境,查找遵循“当前→外层→全局”顺序,未找到则抛出ReferenceError。

JavaScript 中作用域链向上查找变量,是指当代码中访问一个变量时,引擎会从当前执行上下文的词法作用域开始,逐级向外层作用域(即父级函数或全局作用域)搜索该变量,直到找到为止或到达全局作用域顶层。
作用域链的形成基础
作用域链在函数定义时就已确定,由函数创建时所处的词法环境决定,与函数在哪里调用无关。每个函数都有一个内部属性 [[Environment]],指向其定义时的词法环境,这个链式结构就是作用域链。
- 全局作用域是链的终点,所有函数的作用域链最终都连到全局对象(浏览器中是 window,Node.js 中是 global)
- 每层作用域保存自己的变量对象(VO)或词法环境记录(Lexical Environment Record)
- 查找时按“当前 → 外层 → 更外层 → 全局”顺序,一旦命中就停止,不会继续向上
变量查找的具体过程
当执行 console.log(x) 这类语句时,JS 引擎按以下步骤查找 x:
- 先在当前执行上下文的词法环境中找(如当前函数的局部变量、参数、let/const 声明)
- 没找到,就通过 [[Environment]] 指针跳到外层函数的词法环境再查
- 重复该过程,直到找到变量,或抵达全局词法环境
- 若全局也没找到,抛出 ReferenceError
例如:
function outer() {
let x = 10;
function inner() {
console.log(x); // 查找:inner 环境 → outer 环境(找到 x=10)
}
inner();
}
闭包让作用域链“活下来”
即使外层函数执行结束,只要内层函数被引用(比如作为返回值或被赋给变量),它的作用域链仍保留对外层变量的引用,这就是闭包的本质。
立即学习“Java免费学习笔记(深入)”;
- 此时外层作用域不会被垃圾回收,变量持续可访问
- 多次调用同一个闭包函数,共享同一份外层词法环境
- 不同闭包实例(如循环中创建的多个函数)可能绑定不同的外层环境
注意几个常见误区
作用域链只和定义位置有关,和调用栈无关;它不等于调用栈,也不受 this 或 call/apply 影响。
- var 声明会被提升,但查找仍遵循作用域链规则(不是从声明位置开始找)
- let/const 有暂时性死区(TDZ),未初始化前访问会报错,不是找不到,而是禁止访问
- 使用 eval 或 with 会动态修改作用域链,但应避免使用


















