⚡ 编程实验室🏗️ HTML🎨 CSS⚡ JavaScript🐍 Python🗄️ SQL☕ Java⚛️ React💚 Vue🟢 Node.js⚙️ C语言🐘 PHP🐹 Go🔷 TypeScript🐬 MySQL🔧 C++🎯 C#🦀 Rust🅱️ Bootstrap💡 jQuery🎸 Django🍃 MongoDB👗 Sass🎪 Kotlin📊 R语言📋 XML📊 Excel🐘 PostgreSQL🐳 Docker🅰️ Angular🎮 游戏🏠 网站首页

JS Let 与 Const

理解 let/const/var 的区别和作用域 · 难度:入门 · +10XP

JavaScript Let 与 Const 详解

在 ES6(ECMAScript 2015)之前,JavaScript 只有一种声明变量的方式:var。ES6 引入了 letconst,彻底解决了 var 的众多痛点。理解这三者的区别是每个 JavaScript 初学者的必修课,也是面试中的高频考点。

var 的五大问题

var 存在五个主要缺陷:函数作用域而非块级作用域、变量提升容易产生困惑、允许重复声明、全局作用域下会挂载到 window 对象、以及在循环中产生经典的闭包陷阱。这些问题在大型项目中极易导致难以排查的 bug。

// var 的块级作用域问题
if (true) {
  var x = 10;
}
console.log(x); // 10 —— 块外仍能访问!其他语言中这是不可能的

// var 的变量提升(hoisting) console.log(y); // undefined,而非报错 ReferenceError var y = 5;

// var 允许重复声明(let/const 不允许) var z = 1; var z = 2; // 完全没问题,但极易造成混淆

let —— 块级作用域的变量

let 声明的变量只在当前代码块(由花括号 {} 界定)内有效,不可重复声明,存在暂时性死区而不会被提升为 undefined。let 是编写现代 JavaScript 时声明可变变量的推荐方式。

// let 块级作用域
if (true) {
  let a = 100;
  console.log(a); // 100
}
// console.log(a); // ReferenceError: a is not defined

// let 解决循环闭包经典问题 for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); } // 输出: 0, 1, 2(每次迭代都是新的绑定) // 如果用 var,三次输出都是 3

const —— 常量声明

const 用于声明常量,必须在声明时赋值,且不可重新赋值。但要特别注意:const 保证的是引用不可变,而非值不可变。如果 const 指向对象或数组,其属性或元素仍然可以修改。

const PI = 3.14159;
// PI = 3; // TypeError: Assignment to constant variable

// const 对象/数组的内容仍可修改 const arr = [1, 2, 3]; arr.push(4); // 完全合法! arr[0] = 99; // 也合法 —— 修改的是数组内容,不是引用 // arr = [5, 6]; // 报错!试图改变引用

const obj = { name: 'Alice' }; obj.name = 'Bob'; // 合法 —— 修改属性 obj.age = 25; // 合法 —— 新增属性 // obj = {}; // 报错!

三者全面对比

特性varletconst
作用域函数作用域块级作用域块级作用域
提升(Hoisting)提升并初始化为 undefined提升但不初始化(TDZ)提升但不初始化(TDZ)
可重复声明允许不允许不允许
可重新赋值允许允许不允许
声明时必须赋值可选可选必须
全局下挂载到 window
适用场景不再推荐使用需要重新赋值的变量不变的常量/配置

暂时性死区(TDZ)

let 和 const 声明的变量在声明之前不可访问,从块开始到声明语句之间的这段区域称为"暂时性死区"(Temporal Dead Zone)。这是 ES6 专门设计的机制,用于防止在变量未初始化时意外使用它,比 var 的 undefined 初始化更加安全。

// TDZ 演示
{
  // console.log(z); // ReferenceError: Cannot access 'z' before initialization
  let z = 42;
  console.log(z); // 42 —— 声明之后才可访问
}

// typeof 也不再安全 // console.log(typeof undeclaredLet); // ReferenceError console.log(typeof undeclaredVar); // "undefined"(var 时代的老行为)

最佳实践建议

推荐的声明策略(按优先级):

  1. 基础练习:用 let 声明变量 count 初始值为 0,写一个 for 循环将 count 累加到 100,然后尝试在循环外打印 count,观察是否能够访问。
  2. const 陷阱实验:声明 const person = { name: '小明', age: 18 },然后修改 person.age = 19,再尝试 person = { name: '小红' }。观察哪个操作报错,用自己的话解释 const 的真正含义。
  3. 块级作用域实践:分别用 var 和 let 在 if(true){ ... } 代码块中声明变量,在块外分别尝试打印,对比两者的差异并记录结论。
  4. 循环闭包修复:先用 var 写一个 for 循环,在 setTimeout 回调中打印循环变量 i;再将 var 换成 let,观察并解释输出差异。
  5. 综合练习:写一个函数 getGreeting(user),内部用 let 声明 greeting 变量,根据 user.role 用 if 分支赋值不同的问候语,最后用 const 声明一个配置对象 {time: Date.now()},返回拼接后的完整问候语。
Ctrl+Enter
🚀 升级VIP
解锁全部课程+AI助手

🏆 学习排行

加载中...

📊 统计

📖 231 篇
0 完成
🔥 0