前言:为什么你必须重新理解 JavaScript 的变量声明?
你是否曾遇到过这样的困惑?
js
console.log(age); // 输出 undefined,而不是报错?
var age = 18;
console.log(height); // 直接报错!
let height = 1.88;
明明都是声明变量,为什么 var 和 let 的行为完全不同?
为什么 const 声明的"常量"对象,属性还能改?
如果你也曾被这些问题困扰,那么恭喜你,你即将揭开 JavaScript 中最经典、最易错的一块拼图:var、let、const 的本质区别。
一、早期 JavaScript:var 的"糟粕"时代
在 ES6(2015 年)之前,JavaScript 只有一个关键字来声明变量:var。
js
var age = 18;
但 var 的设计存在严重问题,最典型的就是 变量提升(Hoisting)。
什么是变量提升?
JavaScript 的执行分为两个阶段:
- 编译阶段 :检查语法,提升
var和函数声明 - 执行阶段:逐行执行代码
var 声明的变量会在编译阶段就被提升到作用域顶部,但赋值仍然留在原地。
实例说明:
js
console.log(age); // 输出:undefined
var age = 18;
console.log(age); // 输出:18
这段代码的实际执行过程是:
js
// 编译阶段:var age 被提升
var age; // 此时 age = undefined
// 执行阶段:
console.log(age); // undefined
age = 18;
console.log(age); // 18
这种行为完全违背直觉:还没声明就能访问,但值却是
undefined。
⚠️ 二、var 的三大"坏味道"
1. 变量提升导致逻辑混乱
js
function example() {
console.log(a); // undefined
var a = 10;
}
你本意是先声明再使用,但 JavaScript 却允许你在声明前访问,只是值为 undefined。这极易导致 bug。
2. 不支持块级作用域
js
if (true) {
var age = 18;
}
console.log(age); // 18!竟然能访问到
在 if、for 等块级作用域中声明的 var 变量,会泄露到外部作用域。这在大型项目中非常危险。
3. 没有常量的概念
js
var PI = 3.1415926;
PI = 3.14; // 竟然可以修改!
虽然开发者约定"大写字母命名表示常量",但 JavaScript 本身不强制,容易被误改。
三、ES6 的救赎:let 和 const
2015 年,ES6 正式发布,带来了 let 和 const,彻底解决了 var 的问题。
let:现代变量声明的首选
js
let height = 1.88;
height++; // 可以修改
let 的特点:
- 不提升:不能在声明前访问
- 支持块级作用域 :只在
{}内有效 - 不允许重复声明
实例对比:
js
// var 的问题
console.log(age); // undefined
var age = 18;
// let 的正确行为
console.log(height); // 报错!Cannot access 'height' before initialization
let height = 1.88;
const:真正的常量
js
const PI = 3.1415926;
PI = 3.14; // 报错!Assignment to constant variable.
const 声明的变量一旦赋值就不能再修改 ,否则会抛出 TypeError。
注意:
const保证的是引用地址不变,而不是值不可变。
四、常见的错误与报错解析
1. ReferenceError: height is not defined
js
console.log(height); // 报错
原因:变量 height 根本不存在,或在作用域外访问。
2. TypeError: Assignment to constant variable.
js
const PI = 3.14;
PI = 3.15; // 报错
原因:尝试修改 const 声明的变量。
3. ReferenceError: Cannot access 'PI' before initialization
js
console.log(PI);
const PI = 3.14; // 报错
原因:const 和 let 存在暂时性死区(Temporal Dead Zone),不能在声明前访问。
五、暂时性死区:let 和 const 的安全机制
"暂时性死区"听起来很玄乎,其实很简单:
从进入作用域到变量声明完成之前,该变量都不可访问。
示例:
js
{
console.log(a); // 报错!TDZ
let a = 10;
}
这与 var 的"提升但值为 undefined"完全不同,它强制你先声明再使用,提高了代码的可读性和安全性。
六、最佳实践建议
| 场景 | 推荐使用 |
|---|---|
| 普通变量 | let |
| 不会重新赋值的变量 | const |
| 不再使用 | var |
建议:从今天起,彻底告别
var,全面使用let和const。
JavaScript 正在变得越来越"严谨"
var 是 JavaScript 早期设计不完善的产物,而 let 和 const 的出现,标志着 JavaScript 正在向更严谨、更适合大型项目开发的语言演进。
理解它们的区别,不仅能避免常见 bug,更能写出更清晰、更安全的代码。