一、从"变量界的老油条"说起
在ES6出现之前,JavaScript世界里只有一个声明变量的关键字——var。这货就像个"老油条",自由散漫得让人头疼:
- 可以在任何地方声明,随时随地"提升"自己的存在感
- 在全局作用域里声明,就敢往
window对象上凑近乎 - 同一个变量名,想声明几次就声明几次,完全不把规则放在眼里
- 没有块级作用域的概念,在哪里都能"蹦跶"
直到有一天,ES6带来了两个"新青年"——let和const,它们决定要好好整顿一下变量界的风气!
二、let/const的四大"家规",彻底治住了var的"野"性
1. 拒绝"声明提升",做事要有先后顺序
var就像个急性子,不管你在哪里写了var a = 1,它都会偷偷跑到作用域顶部先占个位子。结果就是:
console.log(age); // undefined(不是报错,而是undefined!)
var age = 18;
// 实际上JavaScript会解释成:
var age;
console.log(age);
age = 18;
而let和const就守规矩多了:
console.log(age); // 直接报错:Cannot access 'age' before initialization
let age = 18;
这就像你不能提前使用还没买的东西一样,合情合理!
2. 不当"window"的"跟屁虫",保持独立人格
var在全局作用域声明时,会自动成为window对象的属性,就像个"跟屁虫":
var globalVar = '我是全局变量';
console.log(window.globalVar); // '我是全局变量'
而let和const就有独立人格,即使在全局声明也不会依附于window:
let globalLet = '我也是全局变量';
console.log(window.globalLet); // undefined
3. 拒绝"重复声明",专情到底
var就像个花心大萝卜,同一个变量名可以声明多次:
var age = 18;
var age = 20; // 不报错,age变成20
console.log(age); // 20
而let和const就专情多了,一旦认定了一个变量名,就不允许再变:
let age = 18;
let age = 20; // 直接报错:Identifier 'age' has already been declared
4. 支持"块级作用域",该在哪里就在哪里
var没有块级作用域的概念,只要出现在同一个函数里,就到处乱跑:
{
var myname = '康总';
}
console.log(myname); // '康总'(从块里跑出来了!)
而let和const就规矩多了,待在块级作用域里乖乖不出来:
{
let age = 19;
var myname = '康总';
}
console.log(age); // 报错:age is not defined
console.log(myname); // '康总'
这个特性在循环中特别有用,解决了经典的"循环变量泄漏"问题:
for (let i = 0; i < 10; i++) {
setTimeout(() => console.log(i), 0); // 依次输出0-9
}
for (var i = 0; i < 10; i++) {
setTimeout(() => console.log(i), 0); // 输出10个10
}
三、变量解构赋值:JavaScript界的"拆箱大师"
ES6不仅带来了let和const,还带来了一个"拆箱大师"——变量解构赋值。它能让你更优雅地从数组或对象中提取数据。
1. 数组解构:就像"按顺序领快递"
// 传统方式
let a = 1, b = 2, c = 3;
// 解构赋值方式
let [a, b, c] = [1, 2, 3];
// 还支持嵌套解构
const arr = [1, [2, 3, [4], 5]];
let [a, [b, c, [d], e]] = arr;
console.log(a, b, c, d, e); // 1 2 3 4 5
// 剩余参数
const arr = [1, 2, 3, 4, 5];
let [a, ...b] = arr;
console.log(a, b); // 1 [2, 3, 4, 5]
2. 对象解构:就像"按名字领快递"
const obj = {
name: '康总',
age: 18,
like: {
n: '泡脚'
}
};
// 传统方式
let name = obj.name;
// 解构赋值方式
let {name, age, like: {n}} = obj;
console.log(name, age, n); // '康总' 18 '泡脚'
3. 字符串解构:连字符串都能拆
const [a, b, c, d, e] = 'hello';
console.log(a, b, c, d, e); // 'h' 'e' 'l' 'l' 'o'
// 还能解构字符串的属性
let {length} = 'hello';
console.log(length); // 5
4. 函数参数解构:让函数调用更优雅
function foo({x: a, y: b}) {
return a + b;
}
foo({x: 1, y: 2}); // 3
四、let和const,该怎么选?
let和const都是ES6的"新青年",那我们该怎么选择呢?
- 如果你声明的变量值可能会变,用
let - 如果你声明的变量值不会变,用
const(更安全,推荐优先使用)
const虽然叫"常量",但只是保证指针不变,对于对象和数组,里面的内容还是可以变的:
const person = {name: '康总'};
person.name = '康少'; // 可以修改
person = {}; // 报错:Assignment to constant variable.
五、总结:为什么说let/const是var的"升级版"?
- 更安全:拒绝声明提升,避免了变量未定义就使用的问题
- 更规范:不允许重复声明,保持代码的整洁
- 更灵活:支持块级作用域,让变量的作用范围更清晰
- 更独立:不在全局作用域污染window对象
而变量解构赋值则让我们的代码更简洁、更易读,特别是在处理复杂数据结构时。
现在,你应该明白为什么在现代JavaScript开发中,我们都推荐使用let和const,而尽量避免使用var了吧?下次写代码时,不妨试试这些ES6带来的新特性,相信你会爱上它们的!
(偷偷告诉你:使用let和const,还能减少80%的变量相关bug哦!)