javascript变量查找遵循词法作用域规则,从当前作用域逐层向外查找直至全局;作用域链在函数定义时确定,由嵌套作用域按序组成,查找时从链首开始匹配同名变量优先取最近声明。

JavaScript 中变量查找遵循词法作用域(Lexical Scope)规则,即从当前作用域开始,逐层向外(向上)查找,直到全局作用域。这个过程不依赖函数调用位置,而取决于函数定义时的嵌套结构。
作用域链是查找的核心机制
每次函数执行时,JS 引擎会为它创建一个作用域链(Scope Chain),由当前作用域及所有外层词法作用域按嵌套顺序组成。查找变量时,引擎从链首(当前作用域)开始匹配,一旦找到就停止;找不到则继续向链尾(全局作用域)推进。
- 作用域链在函数定义时就已确定,与调用方式无关(闭包正是基于这一点)
- let/const 声明存在暂时性死区(TDZ),即使在外层作用域声明了同名变量,若当前块内有声明但未初始化,访问会报 ReferenceError
- var 声明会被提升,但赋值不提升;查找时仍按作用域链进行,只是变量可能已声明但值为 undefined
嵌套函数中的变量查找示例
看这个典型例子:
const x = 'global';
function outer() {
const x = 'outer';
function inner() {
const x = 'inner';
console.log(x); // 'inner' —— 找到当前作用域
console.log(this.x); // undefined —— this 不参与作用域链查找
}
inner();
}
执行 inner() 时的作用域链是:[inner 作用域] → [outer 作用域] → [全局作用域]
所以 x 在 inner 内部声明后,就不再向外查找。
遇到同名变量时的优先级
当多层作用域存在同名标识符,JS 总是取离当前执行点最近的那个声明。注意区分“声明位置”和“赋值时机”:
- 函数参数、
let/const和function声明会屏蔽外层同名变量 -
var在同一作用域内重复声明会被忽略,但赋值会覆盖;跨作用域时仍遵循作用域链 -
with和catch语句会临时插入作用域,但实际开发中应避免使用
调试技巧:查看当前作用域链
虽然无法直接打印作用域链,但可通过以下方式辅助判断:
- 在 Chrome DevTools 的断点处,右侧“Scope”面板会清晰列出当前作用域及外层作用域中的变量
- 用
console.dir(functionName)查看函数的[[Scopes]]内部属性(需在断点中执行) - 故意访问不存在的变量,观察报错信息中的“is not defined”,说明查到全局也没找到
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











