必须用const声明不重新赋值的变量;它绑定引用不可变,基本类型无法再赋值,引用类型可修改内部属性但不能重赋值;未初始化即报SyntaxError。

JavaScript 变量声明不是“选一个就行”,let、const 和 var 的行为差异会直接影响代码是否报错、变量能否被修改、作用域是否符合预期——尤其在闭包、循环或模块加载时。
什么时候必须用 const?
const 不是“常量声明语法糖”,它绑定的是「引用不可变」,而非值不可变。只要你不重新赋值给该标识符,就该优先用 const。
- 函数表达式、对象字面量、数组、正则、日期等引用类型,用
const声明后仍可修改其内部属性(如obj.name = 'a'或arr.push(1)),但不能执行obj = {}或arr = [] - 基本类型(
string、number、boolean、symbol、bigint、null、undefined)用const声明后确实无法再赋值,否则报TypeError: Assignment to constant variable - 没有初始化就声明
const会直接报语法错误:const x;→SyntaxError: Missing initializer in const declaration
let 和 var 的作用域到底差在哪?
关键不在“块级”或“函数级”这种标签,而在于「变量是否能在声明前访问」以及「同名变量能否重复声明」。
-
var存在变量提升(hoisting),声明会被移到作用域顶部,但赋值不提升;所以console.log(a); var a = 1;输出undefined,而非报错 -
let和const有暂时性死区(TDZ):从块开始到声明语句前,该变量不可访问,任何读写都会抛ReferenceError -
var允许重复声明(var x = 1; var x = 2;合法);let和const在同一作用域内重复声明会报SyntaxError: Identifier 'x' has already been declared -
for循环中用var声明的变量,循环结束后仍可访问;而let声明的变量只在每次迭代的块内有效,这也是为什么for (let i = 0; i console.log(i), 0);输出0, 1, 2,而换成var就输出三个3
var 在全局作用域下会挂到 window 上吗?
仅限浏览器环境,且仅当脚本运行在非模块(type="module")模式下才成立。这是历史包袱,不是设计特性。
立即学习“Java免费学习笔记(深入)”;
-
var a = 1;→window.a是1(非模块脚本) -
let b = 2;或const c = 3;→window.b和window.c都是undefined - ES 模块(
)中,所有声明(包括var)都不绑定到window,模块有自己独立的顶级作用域 - Node.js 环境中,无论用哪种声明方式,都不会挂到全局对象(
global)上 —— 除非显式赋值,比如global.d = 4
function test() {
if (true) {
var v = 'var';
let l = 'let';
const c = 'const';
console.log(v); // 'var'
console.log(l); // 'let'
console.log(c); // 'const'
}
console.log(v); // 'var' —— var 跨出了 if 块
console.log(l); // ReferenceError: Cannot access 'l' before initialization
console.log(c); // ReferenceError: Cannot access 'c' before initialization
}
真正容易被忽略的,是 TDZ 的边界不只看 {},还和 if、for、try/catch 等语句的实际执行路径有关;一个看似“没走到”的 let 声明,仍会让整个块进入 TDZ。写的时候觉得安全,跑起来却报错,往往就卡在这儿。











