JavaScript变量声明:let与var的核心差异
ES6(ECMAScript 2015)作为JavaScript的现代标准,引入了let和const关键字,彻底改变了变量声明方式。
▍ 作用域:块级 vs 函数级
var的函数作用域特性
if (true) {
var varVar = "我在块内声明";
}
console.log(varVar); // 正常输出 → 变量泄漏到全局
let的块级作用域特性
if (true) {
let letVar = "我被锁在块内";
}
console.log(letVar); // ReferenceError → 变量被严格隔离
关键点:let将变量限制在{}代码块内,彻底解决循环变量泄漏问题:
// var导致的问题
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i)); // 输出5个5
}
// let的解决方案
for (let j = 0; j < 5; j++) {
setTimeout(() => console.log(j)); // 正确输出0-4
}
▍ 变量提升的陷阱
var的变量提升现象
console.log(hoistedVar); // undefined(不会报错)
var hoistedVar = "被提升的变量";
let的暂时性死区(TDZ)
console.log(deadZoneVar); // ReferenceError
let deadZoneVar = "禁止提前访问";
机制说明:let声明的变量在声明前处于"暂时性死区",任何访问尝试都会直接报错。
▍ 重复声明的红线
var允许重复声明
var user = "Alice";
var user = "Bob"; // 无报错 → 潜在风险点
let禁止重复声明
let userId = 1001;
let userId = 1002; // SyntaxError → 强制变量命名规范
▍ 常量声明:const的特殊性
const PI = 3.1415; // 约定使用大写命名
PI = 3.14; // TypeError → 基本类型不可变
const config = { port: 8080 };
config.port = 3000; // 允许修改对象属性
config = {}; // TypeError → 禁止重新赋值
注意:const保证的是变量指向的内存地址不变,与C++等语言的常量机制不同。
作用域类型总结表
| 作用域类型 | 支持的关键字 | 典型场景 |
|---|---|---|
| 全局作用域 | var(不推荐) | 全局配置 |
| 函数作用域 | var | 函数内部变量 |
| 块级作用域 | let/const(推荐) | 循环/条件语句 |
最佳实践建议
- 默认使用
const声明变量 - 需要重新赋值时改用
let - 完全避免使用
var - 使用ESLint等工具强制规范
通过拥抱let和const,我们可以有效避免变量污染、意外覆盖等问题,让JavaScript代码更符合现代工程化标准。