为什么需要let和const?
var、let、const主要在作用域、可变性、变量提升等方面有主要区别可应用于不同的需求场景let 和 const 引入了块级作用域(block scope)是 ES6 推荐的变量声明方式。var 使用的是函数作用域(function scope)存在一些容易导致错误的特性。为什么需要let和constlet和const的出现解决了var使用过程中的几个痛点解决了变量提升导致的混乱var声明的变量会被提升到其作用域顶部变量提升并用undefined初始化能在定义前访问而不报错输出undefined违反直觉。为解决这一问题引入了const和let因这两者存在暂时性死区在此区域外访问会抛出错误ReferenceError提供了块级作用域var没有块级作用域导致在for循环或if语句中声明的变量会泄漏到外部而let和const仅在声明他们的代码块如for循环内或if语句内有效提供了更强的封装性。引入常量const允许声明一个值不能被重新赋值的常量有助于提高代码的可维护性和健壮性防止意外修改API与用法var作用域函数作用域或全局作用域。提升变量提升初始化为undefined。重复声明允许在同一作用域内重复声明。可变性可以重新赋值。function varExample(){ console.log(a);//输出undefined变量提升 var a10; console.log(a);//输出10 iftrue{ a20;// 覆盖了函数作用域中的a console.log(a);//输出20 } console.log(a);//输出20 }let作用域块级作用域 ({...})。提升不提升存在暂时性死区。重复声明不允许在同一作用域内重复声明。可变性可以重新赋值。function letExample(){ console.log(b);// 输出ReferenceError: Cannot access b before initialization (TDZ) let b 10; console.log(b);// 输出10 if(true){ console.log(b);// 输出10 let b20;// 注意如果这里改为b20下面的console就都是20 console.log(b);// 输出:20在块级作用域内可以被重新赋值 } console.log(b);// 输出10 }const作用域块级作用域({...})。提升不提升存在暂时性死区。重复声明不允许在同一作用域重复声明。可变性不能重新赋值声明时必须出示话。function constExample (){ const c30; console.log(c);// 输出30 // c40;//TypeError: Assignment to constant variable. // const c40;//无法重新声明块范围变量“c”。 // 注意对于对象或数组const 保证的是变量绑定的引用不变 // 但对象或数组自身的内容是可变的。 const obj{name:hello}; obj.name你好;// 这是允许的 console.log(obj.name);// 输出你好 }关键注意事项暂时性死区let和const声明的变量从其作用域开始到声明语句之间是暂时性死区TDZ。在此区域内访问变量会抛出ReferenceError。全局对象属性在全局作用域下使用var声明的变量会成为window浏览器环境或Node.js环境对象的属性。cont和let不会。const的不变性const保证的是变量指向的内存地址引用不可变而不是该地址中的数据不可变。对于引用类型如对象、数组其内部属性或元素是可以修改的。优先使用const默认应优先使用const来声明变量只有当确定变量需要被重新赋值时才使用let。这能增强代码的可靠性避免不必要的变量修改。什么是暂时性死区定义从块级作用域开始到变量声明语句之间的区域在此区域内访问变量会抛出ReferenceError。暂时性死区常见陷阱即使外层有同名变量内层的let声明仍会创建新的绑定和 TDZ。let x outer; { console.log(x); // ❌ ReferenceError // 不是因为外层有 x而是本作用域的 let x 声明导致 TDZ let x inner; }function foo(x y, y 2) { return [x, y]; } foo(); // ❌ ReferenceError: Cannot access y before initialization // 原因计算 x y 时y 还在 TDZ 中// 正常情况 typeof undeclaredVar; // ✅ undefined // TDZ 中 typeof x; // ❌ ReferenceError let x;为什么需要暂时性死区// 没有 TDZ 时假设 var tmp true; if (tmp) { console.log(x); // 可能期望访问外层的 x var x 5; // 实际会变量提升不会报错但行为混乱 } // 有 TDZ 时 let tmp true; if (tmp) { console.log(x); // ✅ 明确报错避免意外行为 let x 5; // 块级作用域清晰 }解释一下var 变量提升的本质结合上下文创建过程你会知道其实根本不存在任何的 “提升”变量一直在原地。所谓的 “提升”只是变量的创建过程在上下文创建阶段完成和真实赋值过程在上下文执行阶段完成的不同步带来的一种错觉。执行上下文在不同阶段完成的不同工作才是 “变量提升 “的本质。