JavaScript中变量查找本质是沿词法作用域链逐级向上查找:先查自身,再父函数,最后全局;未找到则抛ReferenceError;该链在函数定义时固化,与调用位置无关。

JavaScript 中嵌套作用域查找变量,本质就是沿着作用域链一级一级往上“问邻居”:先看自己家有没有,没有就去上一层(父函数)找,再没有就继续往上,直到全局;找不到就报 ReferenceError。
作用域链在函数定义时就固定了
关键点在于:作用域链不是运行时动态决定的,而是函数**创建时**根据代码的书写位置(词法结构)就确定下来的。这叫词法作用域。
- 比如一个
inner函数写在outer函数内部,那它的作用域链天然包含inner自身 →outer→ 全局 - 哪怕把
inner函数返回出去、在别的地方调用,它依然按原来的链去找变量(这就是闭包的基础)
查找过程:从当前执行上下文开始逐层向上
每次函数执行,都会创建一个执行上下文,其中包含当前作用域的变量对象(或词法环境),并链接到其外层环境。
- 第一步:在当前函数的局部词法环境中查找变量名
- 第二步:没找到?就顺着
[[Environment]]引用,跳到父级词法环境里找 - 第三步:重复这个过程,直到抵达全局词法环境
- 第四步:全局也没找到 → 抛出
ReferenceError: xxx is not defined
let/const 和 var 的查找行为略有不同
虽然都走同一条作用域链,但访问时机和初始化状态会影响结果:
-
var声明会被提升并初始化为undefined,所以查找能成功,值是undefined -
let和const存在暂时性死区(TDZ):在声明语句之前访问,即使变量在作用域链上存在,也会直接报ReferenceError,而不是返回undefined
常见例子帮你确认链路是否清晰
看这段代码:
const global = 'g';
function outer() {
const o = 'o';
function inner() {
const i = 'i';
console.log(i); // 找自己 → 成功
console.log(o); // 自己没有 → 找 outer → 成功
console.log(global); // 自己没有 → outer 没有 → 全局有 → 成功
}
inner();
}
outer();
此时 inner 的作用域链就是:
inner 的词法环境 → outer 的词法环境 → 全局词法环境
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











