JavaScript let 和 const
JavaScriptlet和const学习笔记ES6 (ECMAScript 2015) 引入了let和const解决了var存在的变量提升、作用域污染和重复声明等问题。1.核心对比表特性varletconst作用域函数作用域块级作用域({})块级作用域({})变量提升是 (值为undefined)是 (但处于暂时性死区)是 (但处于暂时性死区)重复声明允许不允许不允许重新赋值允许允许不允许(必须初始化)全局对象属性是 (window.x)否否适用场景(不推荐)需要变化的变量常量或引用不变的变量2.let详解基本用法用于声明块级作用域的变量允许重新赋值。// 块级作用域示例if(true){letx10;console.log(x);// 10}console.log(x);// ReferenceError: x is not defined// 循环中的经典用法for(leti0;i3;i){setTimeout(()console.log(i),100);}// 输出0, 1, 2 (每个循环都有独立的 i)暂时性死区 (Temporal Dead Zone, TDZ)在代码块中let声明的变量在声明语句之前访问会报错。console.log(a);// ReferenceError: Cannot access a before initializationleta5;对比varvar会提升并初始化为undefined而let在 TDZ 期间完全不可访问。不允许重复声明letx1;letx2;// SyntaxError: Identifier x has already been declared// 函数参数也不能重复functiontest(a,a){}// SyntaxError3.const详解基本用法用于声明常量声明时必须初始化且不能重新赋值。constPI3.14159;PI3.14;// TypeError: Assignment to constant variable.// 必须初始化constx;// SyntaxError: Missing initializer in const declaration对象和数组的“常量”陷阱const保证的是变量指向的内存地址不变而不是对象内容不变。constarr[1,2,3];arr.push(4);// ✅ 允许修改数组内容arr[5,6];// ❌ 报错不能重新赋值给新数组constobj{name:Alice};obj.age25;// ✅ 允许修改对象属性obj{};// ❌ 报错不能重新赋值给新对象冻结对象 (Deep Freeze)如果需要完全禁止修改对象需使用Object.freeze()。constfrozenObjObject.freeze({name:Bob});frozenObj.nameTom;// 静默失败 (严格模式下报错)4.作用域对比varvslet/const函数作用域 vs 块级作用域// var: 函数作用域functiontestVar(){if(true){varx1;}console.log(x);// 1 (x 泄露到了函数外部)}// let/const: 块级作用域functiontestLet(){if(true){lety2;constz3;}console.log(y);// ReferenceErrorconsole.log(z);// ReferenceError}全局作用域vara1;letb2;constc3;console.log(window.a);// 1 (var 挂载到 window)console.log(window.b);// undefined (let 不挂载)console.log(window.c);// undefined (const 不挂载)5.常见陷阱与最佳实践陷阱 1循环中的闭包问题// ❌ var 导致所有定时器共享同一个 ifor(vari0;i3;i){setTimeout(()console.log(i),100);}// 输出3, 3, 3// ✅ let 为每次循环创建新的绑定for(leti0;i3;i){setTimeout(()console.log(i),100);}// 输出0, 1, 2陷阱 2解构赋值// 解构声明let[a,b][1,2];const{name,age}{name:Tom,age:20};// 重新赋值[a,b][3,4];// ✅ 允许 (let)// { name, age } { name: Jerry, age: 25 }; // ❌ 报错 (const 需加括号)({name,age}{name:Jerry,age:25});// ✅ 允许 (加括号避免语法歧义)最佳实践默认使用const如果变量不需要重新赋值优先用const。需要变化时用let仅在变量需要重新赋值时使用let。避免使用var除非维护旧代码否则不再使用var。声明即初始化const必须立即赋值。命名规范常量通常使用UPPER_SNAKE_CASE(如MAX_COUNT)。6.快速决策指南// 1. 这个值以后会变吗// 是 - let// 否 - const// 2. 是对象或数组吗// 是 - const (内容可变但引用不变)// 否 - const (基本类型)// 3. 需要循环计数器吗// 是 - let (for 循环)// 示例constMAX_USERS100;// 常量letcount0;// 计数器constusers[];// 数组引用不变内容可变constconfig{theme:dark};// 对象引用不变7.总结场景推荐关键字常量 (数字、字符串、布尔值)const对象、数组 (引用不变)const循环计数器let需要重新赋值的变量let函数参数const(默认)模块导出const核心原则“能不用let就不用let能不用var就绝对不用var。”