【ES6】day29-let-const

作者:mario 发布时间: 2026-08-26 阅读量:6 评论数:0

第二十九天:let 与 const — 告别 var 的时代

蜗牛往上爬 · 前端工业可视化学习笔记 第 29 篇
正式进入 ES6 标准学习!第一课:let/const。从今天起,我们几乎不再用 var。let 带来块级作用域,const 带来不可变的引用——它们解决了 var 多年的两大痛点:作用域污染和变量提升陷阱。


目录


一、let:块级作用域

var 只有函数作用域,let 有块级作用域({} 内有效)。

// var 穿透块
{
  var a = 10;
}
console.log(a);  // 10

// let 不穿透块
{
  let b = 20;
}
// console.log(b);  // ❌ ReferenceError: b is not defined

为什么重要ifforwhile{} 都会形成作用域,let 让临时变量不"泄漏"到外面,代码更干净。


二、TDZ:暂时性死区

// var 声明提升 → 访问不报错,只是 undefined
console.log(a);  // undefined
var a = 10;

// let 有 TDZ → 声明前访问报错
// console.log(b);  // ❌ ReferenceError: Cannot access 'b' before initialization
let b = 20;

TDZ(Temporal Dead Zone):从代码块开始到 let/const 声明之间的区域。这比 var 的"undefined 陷阱"更安全——错误尽早暴露。


三、不允许重复声明

// var 允许重复(后覆盖前)
var x = 1;
var x = 2;  // ✅

// let 不允许
let y = 1;
// let y = 2;  // ❌ SyntaxError

// 也不允许和函数参数重复
// function fn(a) { let a; }  // ❌

四、const:只读常量

// 声明时必须赋值
// const a;  // ❌ SyntaxError: Missing initializer

const MAX_TEMP = 80;
// MAX_TEMP = 90;  // ❌ TypeError: Assignment to constant variable

// 和 let 一样:块级作用域 + TDZ + 不允许重复声明

命名约定:真正的常量(值永不改变)通常全大写 + 下划线,如 MAX_TEMPAPI_URL


五、const 的坑:内容可以改

const 锁住的是变量指向的地址,不是对象/数组的内容:

// 对象:改属性 ✅,重新赋值 ❌
const device = { name: "CNC-001", temp: 65 };
device.temp = 85;            // ✅ 改内容
device.name = "CNC-002";     // ✅ 改内容
// device = { name: "X" };   // ❌ 换地址

// 数组:push/pop ✅,重新赋值 ❌
const devices = ["CNC-001"];
devices.push("AGV-002");     // ✅ 改内容
// devices = [];             // ❌ 换地址

一句话:const 是"不能换引用",不是"不能改内容"。


六、var 的 for 陷阱与 let 的解法

这是 var 最经典的坑——闭包陷阱:

// var:三次都是 3
for (var i = 0; i < 3; i++) {
  setTimeout(function () { console.log(i); }, 100);
}
// 输出:3 3 3

// let:每次循环都是独立的绑定
for (let j = 0; j < 3; j++) {
  setTimeout(function () { console.log(j); }, 100);
}
// 输出:0 1 2

原理

  • var:只有一份全局 i,回调执行时 i 已是 3

  • let:每次循环创建独立的 j,回调捕获各自的值

这个坑在"批量给按钮绑定事件""定时器读取循环变量"等场景极其常见,用 let 直接解决。


七、实战:重构设备管理系统

把第 10 周的 ES5 代码升级为 ES6 声明方式:

// ===== ES5(旧)=====
var devices = [{ id: "CNC-001", name: "数控机床" }];
function render(filterText) {
  var list = document.getElementById("device-list");
  list.innerHTML = "";
  var data = filterText
    ? devices.filter(function (d) { return d.name.indexOf(filterText) !== -1; })
    : devices;
  data.forEach(function (device) {
    var li = document.createElement("li");
    li.textContent = device.id + " - " + device.name;
    list.appendChild(li);
  });
}

// ===== ES6(新)=====
const devices = [{ id: "CNC-001", name: "数控机床" }];
function render(filterText) {
  const list = document.getElementById("device-list");
  list.innerHTML = "";
  const data = filterText
    ? devices.filter(d => d.name.indexOf(filterText) !== -1)  // 箭头函数
    : devices;
  data.forEach(device => {
    const li = document.createElement("li");
    li.textContent = `${device.id} - ${device.name}`;  // 模板字符串
    list.appendChild(li);
  });
}

声明原则

  • 数据(devices)、DOM 元素(list)→ const(地址不变)

  • 循环变量(i)→ let(会变)

  • 基本不再用 var


八、总结

对比项

var

let

const

块级作用域

TDZ(声明前访问)

不报错(undefined)

报错

报错

重复声明

重新赋值

全局变量进 window

使用原则:默认 const,需要重新赋值时用 let,基本不用 var

🎯 let/const 是 ES6 的地基。明天学解构赋值——最常用的新语法,让代码更优雅。

评论