javascript词法作用域变量查找按定义位置逐层向外,不依赖调用位置;作用域链在函数创建时固化于[[environment]],如inner始终沿outer→全局链查找;未声明变量直接报referenceerror,非返回undefined。

JavaScript 词法作用域中的变量查找,核心是“按代码写的位置,一层层往外找”,不是看函数怎么调用,而是看函数在哪定义的。
查找过程严格按嵌套层级向上推进
当一个函数内部引用某个变量时,引擎会:
- 先查自己作用域(函数体或块内)有没有声明该变量
- 没找到,就去它**定义时的外层作用域**找(不是调用时的外层)
- 继续向上,依次检查父级函数作用域、再上一级……直到全局作用域
- 全程不跳过任何中间层,也不跨分支查找
作用域链在定义时就固定了
函数创建那一刻,JS 引擎就把它外层的词法环境记在内部属性 [[Environment]] 里。这个链不会因为函数被传到别处执行而改变。
例如:
let x = 'global';
function outer() {
let x = 'outer';
function inner() {
console.log(x); // 总是输出 'outer',哪怕 inner 被返回后在别处调用
}
return inner;
}
const fn = outer();
fn(); // 输出 'outer',不是 'global'
因为 inner 定义在 outer 内部,它的作用域链始终是:inner → outer → 全局。
找不到变量就报错,不是返回 undefined
这是容易混淆的关键点:
-
console.log(missing)→ 直接抛 ReferenceError -
typeof missing→ 返回 "undefined"(这是语言特例,绕过了常规查找) - 不存在“隐式返回 undefined”的兜底行为
调试时能直观看到作用域链
在 Chrome DevTools 中打断点,右侧 “Scope” 面板会清晰列出当前执行上下文的作用域链,包括:
- 当前函数的局部变量(Local)
- 它定义时捕获的外层词法环境(Closure)
- 全局对象(Global)
这是验证变量是否真能被访问的最可靠方式。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











