JavaScript中函数作用域屏蔽外部同名变量的本质是词法作用域、变量提升和作用域链查找机制共同作用的结果;只要函数内有var/let/const或参数声明,即覆盖外层同名绑定,未声明时才沿作用域链向上查找。

JavaScript中函数作用域会屏蔽外部同名变量,本质是**词法作用域(Lexical Scoping)+ 变量提升(Hoisting)+ 作用域链查找机制**共同作用的结果。当函数内声明了与外层同名的变量(无论用 var、let 还是 const),该变量在函数内部就“遮蔽”(shadow)了外部变量,后续对该标识符的引用都指向内部声明,而非外部。
函数内部声明优先于外部访问
只要函数体内有同名的 var / let / const 声明,无论声明位置在哪(哪怕在 return 后面),该变量都会在对应作用域内生效,并覆盖外层同名绑定。
-
var声明会被提升到函数顶部,整个函数内都可访问(但初始化未执行前值为undefined) -
let和const存在暂时性死区(TDZ),在声明语句前访问会报错,但一旦声明,即开始屏蔽外部变量
不同声明方式的屏蔽行为差异
虽然都叫“屏蔽”,但 var、let、const 的屏蔽逻辑细节不同:
- 用
var a = 1在函数内声明,会创建一个函数级绑定,完全覆盖外层a;即使外层是let a = 2,函数内仍只认自己的var a - 用
let a = 3在函数内声明,会创建块级绑定,在该函数作用域内屏蔽所有同名外层变量(包括var声明的) - 函数参数也参与屏蔽:若函数定义为
function fn(a) { console.log(a); },调用fn(10)时,参数a就是函数作用域内的第一绑定,外层let a = 5不会影响它
没有声明时才沿作用域链向上查找
只有当当前作用域**完全没有该变量的声明**时,JS 引擎才会沿着作用域链向外层查找。一旦某层找到了声明,查找立即停止——这就是屏蔽发生的临界点。
立即学习“Java免费学习笔记(深入)”;
- 例如外层
let x = 'outer',函数内没写let x或var x,直接写console.log(x),就会输出'outer' - 但如果函数内写了
let x = 'inner',哪怕只在某个if块里,整个函数体中对x的访问都以这个新绑定为准(注意 TDZ 范围)
常见误解:赋值不等于声明
单纯给一个未声明的变量赋值(如函数内写 x = 'new'),不会触发屏蔽,反而可能意外创建全局变量(非严格模式)或报错(严格模式)。屏蔽只由 声明语句(var/let/const/函数参数/函数声明)触发。
- 错误示例:不是屏蔽 —— 外层
let y = 1,函数内写y = 2→ 修改的是外层y - 正确屏蔽:是屏蔽 —— 函数内写
let y = 2→ 新建局部y,外层y不再可访问










