2015 年,ES6(ECMAScript 2015)的发布成为 JavaScript 发展的分水岭。在此之前,JS 作为一门 "轻量脚本语言",虽因单线程、简单易用的特性风靡前端,但也暴露了诸多短板:变量提升导致的逻辑混乱、缺乏类和模块机制、代码冗余难以维护…… 这些问题让它在大型项目中力不从心。
而 ES6+(ES6 及后续版本)的出现,彻底改变了这一局面。它借鉴了众多企业级语言的优秀特性,补上了 JS 作为 "大型开发语言" 的最后一块拼图。今天,我们就拆解 ES6 + 中最实用的核心特性,看看它们如何让 JS 代码更优雅、更高效。
一、解构:一次性 "拆包" 的优雅操作
在 ES6 之前,要从数组或对象中提取多个值并赋值给变量,需要重复写多行代码。而解构(Destructuring) 让这一过程变得极其简洁。
1. 数组解构:按位置 "拆"
javascript
运行
// ES5 写法:繁琐重复
const arr = [10, 20, 30];
const a = arr[0];
const b = arr[1];
const c = arr[2];
// ES6 数组解构:一行搞定
const [a, b, c] = [10, 20, 30];
console.log(a, b, c); // 10 20 30
进阶用法:
- 跳过元素:
const [a, , c] = [10, 20, 30];(a=10,c=30) - 嵌套解构:
const [a, [b, c]] = [10, [20, 30]];(a=10,b=20,c=30) - 剩余元素:
const [a, ...rest] = [10, 20, 30];(rest = [20, 30],...是扩展运算符,下文详解)
2. 对象解构:按键名 "拆"
对象解构通过 "键名匹配" 提取值,无需关心顺序,比数组解构更灵活:
javascript
运行
// ES5 写法:重复访问对象属性
const user = { name: '张三', age: 20, gender: '男' };
const name = user.name;
const age = user.age;
const gender = user.gender;
// ES6 对象解构:直接按键名提取
const { name, age, gender } = user;
console.log(name, age, gender); // 张三 20 男
进阶用法:
- 重命名变量:
const { name: userName } = user;(将 name 赋值给 userName) - 嵌套解构:
const { info: { address } } = { info: { address: '北京' } };(address = ' 北京 ') - 默认值:
const { age = 18 } = { name: '李四' };(age 默认 18,避免 undefined)
核心价值:解构的本质是 "模式匹配"—— 左右两边结构一致即可自动赋值,大幅减少重复代码,尤其在处理接口返回数据时极为高效。
二、扩展运算符(...):"展开" 与 "收集" 的神器
...(扩展运算符)是 ES6 中最灵活的特性之一,它有两个核心功能:展开(将集合拆成单个元素) 和 收集(将多个元素合并成集合) 。
1. 展开数组:打破数组的 "包裹"
javascript
运行
// 合并数组(ES5用concat,ES6用...更直观)
const arr1 = [1, 2];
const arr2 = [3, 4];
const merged = [...arr1, ...arr2]; // [1,2,3,4]
// 复制数组(避免引用传递)
const original = [1, 2, 3];
const copy = [...original]; // 相当于浅拷贝,copy修改不影响original
// 函数传参(替代apply)
const nums = [10, 20, 30];
Math.max(...nums); // 等价于Math.max(10,20,30),结果30
2. 展开对象:合并对象的便捷方式
ES2018 将扩展运算符扩展到对象,可快速合并对象(后出现的属性会覆盖前面的):
javascript
运行
const obj1 = { name: '张三', age: 20 };
const obj2 = { age: 21, gender: '男' };
const mergedObj = { ...obj1, ...obj2 };
// { name: '张三', age: 21, gender: '男' }(age被obj2覆盖)
3. 收集剩余元素:将零散值 "打包"
配合解构使用时,...可将剩余元素收集成数组:
javascript
运行
const [first, ...rest] = [1, 2, 3, 4];
// first = 1,rest = [2,3,4]
// 函数参数中收集剩余参数
function sum(first, ...others) {
return first + others.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // 1+2+3+4=10
核心价值:...让数组 / 对象的合并、复制、传参更直观,替代了 ES5 中concat、apply等繁琐写法,且语义更清晰。
三、对象属性简写:少写一行是一行
当对象的属性名与变量名相同时,ES6 允许省略属性值的变量名,直接简写:
javascript
运行
const name = '张三';
const age = 20;
// ES5 写法:属性名和变量名重复
const user = {
name: name,
age: age,
sayHi: function() {
console.log('hi');
}
};
// ES6 简写:更简洁
const user = {
name, // 等价于name: name
age, // 等价于age: age
sayHi() { // 方法简写,省略function
console.log('hi');
}
};
核心价值:减少冗余代码,让对象定义更清爽,尤其在 React 组件传参、接口数据组装时高频使用。
四、模板字符串:告别字符串拼接的 "加号地狱"
ES6 之前,拼接字符串(尤其是多行或带变量的)需要大量+和转义符(\n),既繁琐又易错。模板字符串用反引号(`)包裹,支持直接换行和 ${} 插值,彻底解决这一问题。
javascript
运行
const name = '张三';
const age = 20;
// ES5 拼接:加号和转义符满天飞
const info = '姓名:' + name + '\n' + '年龄:' + (age + 1) + '岁';
// ES6 模板字符串:直观如"自然语言"
const info = `姓名:${name}
年龄:${age + 1}岁`; // 直接换行,${}内可写表达式
console.log(info);
// 姓名:张三
// 年龄:21岁
核心价值:${}中可以放任意表达式(变量、运算、函数调用等),配合换行支持,让字符串处理从 "体力活" 变成 "直观操作"。
五、for...of:更优雅的遍历方式
JS 中遍历数组的方式很多(for 循环、forEach、for...in),但各有缺陷:for 循环需要手动控制索引,forEach 不能 break,for...in 会遍历原型链。ES6 的for...of则集百家之长:
javascript
运行
const arr = ['a', 'b', 'c'];
// for...of 遍历:简洁且支持break
for (const item of arr) {
if (item === 'b') break; // 可以中断循环
console.log(item); // 输出 'a'
}
// 遍历字符串(字符串也是可迭代对象)
for (const char of 'hello') {
console.log(char); // 依次输出 h e l l o
}
核心价值:语义化更强("对于每个元素"),支持 break/continue,且能遍历所有 "可迭代对象"(数组、字符串、Map、Set 等),是遍历的首选方案。
六、BigInt:终于能正确处理 "大数" 了
JS 中Number类型有精度限制(最大安全整数为2^53 - 1),超过这个值的整数计算会失真:
javascript
运行
console.log(9007199254740992 === 9007199254740993); // true(明显错误)
ES2020 引入BigInt(大整数类型),解决了这一问题。声明方式是在整数后加n:
javascript
运行
// 用BigInt处理大数
const bigNum1 = 9007199254740992n;
const bigNum2 = 9007199254740993n;
console.log(bigNum1 === bigNum2); // false(正确)
// 运算(注意:BigInt不能直接和Number运算)
console.log(bigNum1 + bigNum2); // 18014398509481985n
使用场景:处理超过2^53 - 1的整数(如后端返回的雪花 ID、大金额计算等)。
七、指数运算(**):简洁的幂计算
ES7(2016)引入**运算符,替代Math.pow,让幂计算更直观:
javascript
运行
// ES5:Math.pow(底数, 指数)
console.log(Math.pow(2, 3)); // 8
// ES7:底数**指数
console.log(2 **3); // 8
console.log(10** 6); // 1000000(10的6次方)
核心价值:写法更简洁,语义更清晰,尤其在处理数学计算时更自然。
八、函数默认参数:告别 "||" 的坑
ES6 之前,设置函数默认参数需要用||,但它会把 0、'' 等 "假值" 也覆盖掉。ES6 的默认参数则只在参数为undefined时生效:
javascript
运行
// ES5 写法:有坑(0会被替换成默认值)
function multiply(a, b) {
b = b || 1; // 如果b是0,会被改为1,错误!
return a * b;
}
multiply(5, 0); // 5*1=5(错误,预期0)
// ES6 默认参数:只在b为undefined时生效
function multiply(a, b = 1) {
return a * b;
}
multiply(5, 0); // 5*0=0(正确)
multiply(5); // 5*1=5(正确,b用默认值)
核心价值:更精准地控制默认值,避免||的逻辑陷阱,且参数默认值可以是表达式甚至函数调用。
总结:ES6 + 为何让 JS 脱胎换骨?
从上述特性可以看出,ES6 + 的设计核心是 "优雅" 与 "实用":
- 解决历史痛点(如变量提升、大数精度、默认参数陷阱);
- 简化重复操作(解构、扩展运算符、属性简写);
- 提升代码可读性(模板字符串、for...of);
- 适配大型项目(为后续的 class、模块系统打下基础)。
这些特性不仅让开发者写得更爽,更让 JS 从 "小打小闹的脚本" 成长为能支撑大型应用的 "企业级语言"。如今,ES6 + 已成为前端开发的基础,熟练掌握这些特性,是从 "初级开发者" 到 "中级开发者" 的必经之路。
如果觉得有用,欢迎点赞收藏,下次写代码时翻出来对照实践~