JavaScript变量宣言三剑客:var、let、const的奇幻冒险
引言:JavaScript的进化史
从前从前,在编程语言的王国里,有一位名叫JavaScript的小伙子。1995年他出生时,只有var
这一种变量声明方式。那时的他天真烂漫,行为随性,直到2015年ES6标准的到来,才为他带来了let
和const
两位严谨的伙伴,从此开启了JavaScript的"成人礼"。
第一章:老大哥var的"任性人生"
1.1 var的"越狱"行为
function prison() {var prisoner = "I'm here!";if (true) {var prisoner = "I escaped!"; // 同一个囚犯轻松越狱}console.log(prisoner); // "I escaped!"
}
var就像个不守规矩的魔术师,它无视代码块的边界(块级作用域),在任何地方都能重新声明自己。这种"变量提升"(hoisting)的特性常常让新手开发者抓狂:
console.log(magician); // undefined 而不是报错!
var magician = "Houdini";
1.2 var的"派对狂欢"问题
在循环中使用var就像举办一场失控的派对:
for (var i = 0; i < 3; i++) {setTimeout(() => console.log(i), 100); // 3, 3, 3
}
所有客人(回调函数)看到的都是派对结束后的狼藉(最终值),而不是派对进行时的每个精彩瞬间。
第二章:let的"纪律部队"
2.1 let的"军事化管理"
ES6派来的"纪律委员"let解决了var的所有毛病:
let soldier = "at attention";
let soldier = "at ease"; // SyntaxError: 已经声明过啦!{let recruit = "in training";
}
console.log(recruit); // ReferenceError: 新兵不得擅自离营!
2.2 let的"时间胶囊"效应
在循环中使用let,每个迭代都会创建一个新的词法环境,就像给每个客人发了一个专属时间胶囊:
for (let i = 0; i < 3; i++) {setTimeout(() => console.log(i), 100); // 0, 1, 2
}
2.3 暂时性死区(TDZ)
let有个特别的安保措施——暂时性死区(Temporal Dead Zone):
console.log(agent); // ReferenceError: 特工身份尚未解密!
let agent = "007";
第三章:const的"终极防线"
3.1 const的"不可变宣言"
const就像军事基地的警告标志:
const MISSILE_SILO = "Danger Zone";
MISSILE_SILO = "Safe Zone"; // TypeError: 核按钮岂能随便按!
行业惯例:const常量全大写,像警示牌一样醒目。
3.2 const的"变形记"
但const有个神奇的特性——对于对象和数组,它锁定的只是"容器",而不是"内容物":
const LAB_SPECIMEN = {species: "werewolf"
};
LAB_SPECIMEN.species = "vampire"; // 完全合法!
LAB_SPECIMEN = {}; // TypeError: 容器不可更换!
3.3 冻结对象
想要真正不可变?可以使用Object.freeze
:
const HERO = Object.freeze({name: "Superman"
});
HERO.name = "Batman"; // 静默失败或在严格模式下报错
第四章:作用域大逃杀
4.1 作用域层级
JavaScript的作用域就像俄罗斯套娃:
- 全局作用域:window/global这个大套娃
- 函数作用域:var认识的中号套娃
- 块级作用域:let/const认识的迷你套娃
const WORLD = "Earth"; // 全球通告function continent() {var country = "China"; // 全国通告if (true) {let city = "Beijing"; // 本市通告}
}
4.2 作用域链的"寻宝游戏"
当JavaScript查找变量时,它会像玩寻宝游戏一样层层向上:
const TREASURE = "gold"; // 第三层function pirateShip() {var TREASURE = "silver"; // 第二层if (true) {let TREASURE = "bronze"; // 第一层console.log(TREASURE); // "bronze"}
}
第五章:现代JavaScript开发指南
5.1 变量声明新规范
- 默认使用const:除非需要重新赋值
- 需要重新赋值时用let:如循环计数器
- 避免使用var:除非维护老旧代码
- 命名约定:
- CONSTANTS_IN_UPPERCASE
- camelCaseForVariables
- PascalCaseForConstructors
5.2 常见陷阱警示牌
🚧 const
不保证对象内容不可变!
🚧 let
在同一个作用域内不可重复声明!
🚧 var
会穿透if/for等块级作用域!
🚧 未声明的变量会自动成为全局变量(严格模式禁止)!
第六章:幕后原理探秘
6.1 执行上下文的秘密
JavaScript引擎处理变量声明分为三个阶段:
- 创建阶段:
- var:初始化为undefined
- let/const:未初始化(TDZ)
- 执行阶段:
- 变量赋值
- const必须立即赋值
6.2 词法环境的结构
每个执行上下文都有一个关联的词法环境:
结语:选择正确的工具
就像超级英雄各有专长:
- var:像死侍,打破常规但难以控制
- let:像美国队长,纪律严明但灵活
- const:像钢铁侠的战甲,坚固可靠但有特殊机制
在现代JavaScript开发中,我们应该:默认用const,需要重新赋值用let,永远不要用var(除非你在写1995年的复古代码)。
记住:伟大的代码能力伴随着重大的责任——选择正确的变量声明方式,让你的代码既安全又富有表现力!