JavaScript变量查找严格遵循词法作用域,即按代码嵌套结构向上逐层搜索,与调用方式无关;var归属函数作用域,let/const归属块级作用域,函数声明和箭头函数均遵守该规则。

JavaScript 中变量查找完全依赖词法作用域——不是看函数怎么被调用,而是看它在代码里写在哪一层。声明变量时选对关键字(var、let、const),本质上就是在明确告诉 JS 引擎:“这个变量归哪个词法作用域管”。只要声明方式和嵌套结构匹配,查找就自然顺畅。
声明位置决定词法作用域归属
词法作用域在代码写完那一刻就固定了,不随运行时改变。所以变量能被谁访问,只取决于它声明时所处的代码块层级:
- 写在最外层(不在任何函数或花括号内)→ 归属全局词法作用域
- 写在一个函数内部(无论是否在 if/for 里)→ 归属该函数的词法作用域(var 也如此)
- 写在一对花括号 {} 内,且用 let 或 const 声明 → 归属这个块级词法作用域(比如 if{}、for{}、{})
不同声明方式对应不同作用域边界
同一个位置用不同关键字声明,变量“归属感”完全不同:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
- var:只认函数边界。哪怕写在 if 里,也会被提升到整个函数顶部,外部仍可访问(在函数内)
- let / const:严格认花括号 {}。if{}、for{}、{} 都算独立作用域,块外访问直接报 ReferenceError
- 函数声明(function fn(){}):也遵循词法作用域,且会被提升;箭头函数没有自己的 this,但作用域链查找规则不变
查找过程:沿着词法嵌套向上逐层找
执行到一个变量引用时,JS 引擎按以下顺序查找:
立即学习“Java免费学习笔记(深入)”;
- 先查当前词法作用域(比如当前函数体、当前块)有没有该变量声明
- 没有就往上一级词法作用域查(比如外层函数、全局)
- 一直查到全局,还没找到就抛 ReferenceError
- 注意:不会跨函数调用栈找,只看代码嵌套结构。哪怕 inner 是被 outer.returnInner() 返回后在别处调用,它依然沿用定义时的 outer 作用域
避开常见干扰项:提升与 TDZ 不改变查找逻辑
变量提升(hoisting)和暂时性死区(TDZ)影响的是“能不能读/写”,不是“去哪找”:
- var a 被提升:声明被移到函数顶,但赋值不动 → 查找路径没变,只是初始值是 undefined
- let a 有 TDZ:从块开始到声明语句前,访问就报错 → 查找路径依然存在,只是引擎主动拦截了非法访问
- 关键点:无论有没有提升或 TDZ,引擎始终按词法嵌套层级去搜索,这点从未动摇

















