let 和 const 声明变量不参与声明提升,而是进入暂时性死区(tdz),声明前访问直接报错;它们具有块级作用域,且应优先使用 const,仅在需重新赋值时用 let。

用 let 和 const 声明变量,能从根本上绕过变量提升的陷阱,关键在于它们不参与“声明提升”,而是进入“暂时性死区”(TDZ)——在声明前访问直接报错,而不是返回 undefined。
let/const 不提升声明,只保留“不可访问”的状态
var 声明会被引擎提前到作用域顶部,但赋值留在原地,导致声明前读取是 undefined;而 let/const 的声明虽在编译阶段被识别,但变量在声明语句执行前处于 TDZ,任何访问(包括 typeof、console.log)都会抛出 ReferenceError。
-
console.log(a); let a = 1;→ 报错,明确提示“未初始化前不可访问” -
console.log(typeof b); const b = {};→ 同样报错,不像 var 那样“安全”返回"undefined" - 这种设计强制开发者按顺序书写逻辑,避免因误读执行顺序引发的隐性 bug
块级作用域天然隔离变量生命周期
let 和 const 的作用域限定在最近的花括号 {} 内,包括 for 循环、if 分支、函数体内部等。这意味着变量不会意外泄露到外层,也不会被后续同名声明覆盖。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- for 循环中用
let i,每次迭代都创建独立绑定,闭包能正确捕获当前值 - if 块内声明
const user = {...},块外无法访问,杜绝了“本该私有却全局可见”的污染 - 函数内嵌套块中重复使用相同变量名(如
let id),彼此互不影响
const 优先 + let 按需,减少可变性带来的不确定性
变量是否需要重新赋值,决定了该用 const 还是 let。默认用 const 能让引擎和团队快速识别“此值不变”,既防止误赋值,也减少因状态突变引发的调试困难。
- 对象或数组用 const 声明后,内容仍可修改(如
obj.name = "new"),但变量本身不能指向新地址 - 循环计数器、临时中间值、条件分支中的不同结果,适合用 let
- 禁止用 var,它同时带来函数作用域模糊、可重复声明、变量提升三重风险
实际编码中要警惕的 TDZ 边界
暂时性死区不是语法糖,而是运行时真实存在的限制。尤其在模块导入、类字段初始化、箭头函数参数默认值等场景,容易无意中触达 TDZ。
- 类中定义
const VERSION = "1.0"是合法的;但写成const VERSION = this.baseVersion就会报错,因为this在构造函数执行前不可用 - 模块顶层代码中,import 在所有声明之前执行,但 import 的绑定仍受 TDZ 约束(例如动态 import 返回 Promise,其 resolve 值不能在声明前引用)
- 避免在函数参数默认值里引用尚未声明的 let/const 变量
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










