遮蔽效应是词法作用域下标识符绑定路径被重定向的结果——内层同名声明使查找“找到即停”,外层变量仍存在但不可见;JavaScript在编译阶段构建作用域链,var、let、const均可遮蔽但作用域和提升行为不同。

遮蔽效应不是运行时“覆盖”变量,而是词法作用域下标识符绑定路径被重新定向的结果——只要内层作用域声明了同名变量,所有对该名称的引用就会自动指向它,外层同名变量依然存在,只是不可见。
遮蔽在声明时就已确定
JavaScript 引擎在编译阶段(执行前)就构建好作用域链,并根据代码的书写位置(词法位置)决定每个变量声明的作用域范围。一旦某一层作用域(函数体、块{}、模块顶层等)中出现 let、const 或 var 声明的同名变量,该作用域及其所有嵌套子作用域中,对该变量名的所有读写操作,都会绑定到这个新声明上。
- var x = 10 在函数开头 → 整个函数体内 x 都指它,哪怕后面 if 块里再写 var x = 20,也因 var 没有块级作用域而仍属于函数作用域,实际是重复声明(不报错但无效)
- let x = 100 在 if 块内 → 只在该 if 块及其内部作用域生效,块外仍可访问外层的 x
- 即使外层是 const x = 1,内层用 let x = 2 也能成功遮蔽——声明方式不同不影响遮蔽成立
查找过程:从内到外,找到即停
当代码中出现一个变量名(如 console.log(x)),引擎按以下顺序查找:
- 先查当前执行上下文的词法环境(Local Scope)→ 找到就用,不再继续
- 没找到,就沿作用域链向上查外层词法环境(Closure / Outer Function)
- 一直查到全局词法环境(Global Scope),还没找到就报 ReferenceError
遮蔽之所以发生,正是因为“找到即停”——内层声明让查找在第一层就结束了,根本不会走到外层。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
不同声明方式带来的遮蔽差异
var、let、const 都能触发遮蔽,但行为关键不同:
- var:函数作用域;声明会被提升,但遮蔽范围仍是整个函数;{ var x = 5 } 中的 var 实际属于外层函数,不构成真正块级遮蔽
- let/const:块级作用域;严格按 {} 边界生效;同一块内重复声明直接报错;存在暂时性死区(TDZ),在声明语句前访问会报 ReferenceError
- 未声明直接赋值(如 x = 10)不触发遮蔽;非严格模式下可能意外创建全局变量;严格模式下直接抛错
遮蔽只影响标识符,不影响对象属性
这是常见误解点:
- let obj = {val: 1}; 后又 let obj = {val: 2}; → 发生遮蔽,两个 obj 是不同对象
- let obj = {val: 1}; 后没声明新 obj,只写 obj.val = 99; → 不遮蔽,直接修改原对象属性
- 想访问被遮蔽的外层对象?只能提前保存引用(如 const outerObj = obj),或避免同名设计

















