javascript词法作用域由函数定义位置决定,与调用位置无关;作用域链逐级向上查找,不可跳过;块级作用域(let/const)纳入链中,var不创建;同名变量仅遮蔽而非销毁外层变量。

词法作用域由函数定义位置锁定
JavaScript 的词法作用域在函数创建时就已确定,和函数在哪里调用完全无关。比如一个函数写在 outer 函数内部,那它的第一层父级作用域就是 outer;如果写在全局下,它直接连全局,跳过所有中间函数。
这种“认爹不认妈”的规则意味着:哪怕把内层函数 return 出去,在别处调用,它查找变量的路径依然按当初写的嵌套结构走。
作用域链是逐级向上、不可跳过的查找路径
当执行 console.log(x) 时,引擎严格按顺序查找:
- 先查当前函数自身的词法环境(参数、
let/const/var声明) - 没找到,就跳到外层函数的作用域里找
- 还没找到,继续往上,直到全局作用域
- 任一环节命中即停止,不会绕开某一级去“抄近路”
这个过程像回家找钥匙:先翻自己书桌(当前作用域),没有就去客厅茶几(父级),再没有就查玄关挂钩(全局),不会跳过客厅直奔玄关。
块级作用域也参与链式结构
if、for、{} 这类代码块,只要用了 let 或 const,就会生成一个独立的作用域节点,并纳入作用域链。
例如:
function fn() {
if (true) {
let x = 1;
}
console.log(x); // 报错:x 不在 fn 自身作用域,也不在全局,链上找不到
}
而 var 不创建块级作用域,所以同段代码中用 var x = 1,console.log(x) 就能输出 1——因为 x 属于 fn 函数作用域。
同名变量只是遮蔽,不是覆盖或销毁
内层声明同名变量,只是让外层那个暂时不可见,外层变量依然存在且完整。
比如:
-
let a = 1; function f() { let a = 2; console.log(a); }→ 输出2 - 删掉
f里的let a = 2,输出立刻变成1
这说明外层 a 一直都在,只是被遮住了。这种遮蔽发生在所有层级,包括 var,但因变量提升机制,var 的行为更隐蔽;let/const 在声明前访问会直接进 TDZ 报错。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











