3、ES6核心语法:let/const、解构赋值、模板字符串、箭头函数、Symbol、Set/Map
ES6 的发布,说实话,是 JavaScript 发展史上一个里程碑。我到现在还记得刚接触那会儿,看到 let 和 const 时的兴奋感——终于不用再被 var 的变量提升折磨了。这一章,咱们就把 ES6 里最核心、最常用的几个语法点过一遍。这些都是我每天写代码都会用到的东西,你吃透了它们,写出来的代码会干净很多。
3.1 let 与 const:告别 var 的混乱
我个人习惯,现在写代码基本不用 var 了。能用 const 就用 const,确定要重新赋值的才用 let。为什么?因为这样能减少很多意想不到的 bug。
let 和 const 有两个核心特性:块级作用域 和 暂时性死区。
- 块级作用域:说白了,就是花括号
{}内部就是一个独立的作用域。变量只在当前块内有效。 - 暂时性死区:在变量声明之前,你不能访问它。否则会报
ReferenceError。
// 以前用 var 的坑
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100); // 输出 5 个 5
}
// 用 let 就正常了
for (let j = 0; j < 5; j++) {
setTimeout(() => console.log(j), 100); // 输出 0, 1, 2, 3, 4
}
const。只有当你明确知道这个变量需要重新赋值时,才改用 let。这能帮你写出更可预测的代码。
const 保证的是变量指向的内存地址不变,而不是值不可变。对于对象和数组,你仍然可以修改它们的属性或元素。
3.2 解构赋值:从数组和对象中快速提取数据
解构赋值,说白了就是一种「模式匹配」。它让你能从数组或对象中快速提取数据,赋值给变量。我在项目中经常用它来处理 API 返回的数据,非常方便。
// 数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [3, 4, 5]
// 对象解构
const user = { name: '张三', age: 30, email: 'zhangsan@example.com' };
const { name, email } = user;
console.log(name); // 张三
// 嵌套解构
const data = { person: { address: { city: '北京' } } };
const { person: { address: { city } } } = data;
console.log(city); // 北京
你想想看,如果没有解构赋值,你得写多少行 const name = user.name 这样的代码?解构赋值让代码变得简洁多了。
实用技巧:解构时还可以设置默认值。比如 const { name = '匿名' } = user,当 user.name 为 undefined 时,name 就会取默认值。
3.3 模板字符串:告别字符串拼接
以前拼接字符串,得用加号 +,写起来又丑又容易出错。模板字符串用反引号 ` 包裹,用 ${} 嵌入变量或表达式,直观多了。
const name = '李四';
const age = 25;
// 旧方式
const greeting = '你好,' + name + ',你今年' + age + '岁了。';
// 模板字符串
const greetingNew = `你好,${name},你今年${age}岁了。`;
// 还可以写表达式
const info = `明年你${age + 1}岁了。`;
模板字符串还支持多行文本,不用再写 \n 了。我记得有一次写一个复杂的 SQL 查询,用模板字符串直接换行,代码可读性提升了一大截。
3.4 箭头函数:更简洁的函数写法
箭头函数 => 是 ES6 最受欢迎的语法之一。它有两个主要特点:语法简洁 和 不绑定 this。
// 传统函数
const add = function(a, b) {
return a + b;
};
// 箭头函数
const addArrow = (a, b) => a + b;
// 只有一个参数时,可以省略括号
const double = x => x * 2;
// 没有参数时,必须写括号
const sayHello = () => '你好';
箭头函数不绑定 this,它会捕获所在上下文的 this 值。这一点在回调函数中特别有用。
function Timer() {
this.seconds = 0;
// 传统函数:this 指向 window 或 undefined
setInterval(function() {
this.seconds++; // 错误!
}, 1000);
// 箭头函数:this 指向 Timer 实例
setInterval(() => {
this.seconds++; // 正确!
}, 1000);
}
new 调用。另外,它也没有 arguments 对象。如果你需要这些特性,还是用传统函数吧。
3.5 Symbol:独一无二的值
Symbol 是 ES6 新增的一种原始数据类型。它表示独一无二的值,主要用来解决对象属性名冲突的问题。
const sym1 = Symbol('描述');
const sym2 = Symbol('描述');
console.log(sym1 === sym2); // false,即使描述相同
// 作为对象属性
const obj = {
[sym1]: '这是 Symbol 属性'
};
console.log(obj[sym1]); // '这是 Symbol 属性'
Symbol 最常见的用途是定义对象的私有属性或常量。比如,你可以用 Symbol 来定义一些内部使用的属性,避免被外部意外覆盖。
小技巧:使用 Symbol.for() 可以创建全局共享的 Symbol。比如 Symbol.for('foo') 会在全局注册表中查找或创建一个 Symbol。
3.6 Set 与 Map:更强大的集合与映射
ES6 之前,JavaScript 只有数组和对象。现在有了 Set 和 Map,处理数据集合方便多了。
Set:不重复的集合
Set 类似于数组,但成员的值都是唯一的,没有重复。
const set = new Set([1, 2, 3, 3, 4, 4, 5]);
console.log(set); // Set { 1, 2, 3, 4, 5 }
// 常用操作
set.add(6);
set.delete(1);
console.log(set.has(2)); // true
console.log(set.size); // 5
// 数组去重
const arr = [1, 2, 2, 3, 3, 4];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 2, 3, 4]
Map:键值对集合
Map 类似于对象,但它的键可以是任意类型(包括对象、函数等),而且有更丰富的 API。
const map = new Map();
// 设置键值对
map.set('name', '王五');
map.set(123, '数字键');
map.set({ id: 1 }, '对象键');
// 获取值
console.log(map.get('name')); // '王五'
// 遍历
map.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
// 与对象互转
const obj = Object.fromEntries(map);
const map2 = new Map(Object.entries(obj));
我的经验:在需要频繁增删键值对,或者键不是字符串的场景下,Map 比普通对象更合适。比如缓存数据、存储 DOM 元素与数据的映射关系等。
好了,ES6 的核心语法就这些。说实话,这些特性现在已经是 JavaScript 的标配了。你写 React、Vue 或者 Node.js,几乎天天都会用到它们。多练练,很快就能上手。