ES6(ECMAScript 2015)新特性全解析:彻底改变 JavaScript 开发的 18 个核心特性
ES6(即 ECMAScript 2015)是 JavaScript 语言发展史上的里程碑版本。在此之前,JavaScript 的语法相对简陋,面对大型项目开发时显得力不从心;而 ES6 通过引入块级作用域、类、模块、异步方案等特性,彻底提升了语言的规范性、可读性和可维护性,直接推动了 React、Vue 等现代前端框架的兴起。
本文将从「实用角度」出发,详细拆解 ES6 的 18 个核心新特性,每个特性均包含特性说明、语法示例、使用场景,既是新手入门的指南,也可作为开发中的速查手册。
一、变量声明:let /const—— 解决 var 的 “历史遗留问题”
在 ES6 之前,JavaScript 只有「函数作用域」和「全局作用域」,var声明的变量存在变量提升、重复声明覆盖、块级无隔离三大问题。let和const的出现,彻底解决了这些痛点。
1. let:块级作用域的变量
-
特性说明:
- 「块级作用域」:仅在
{}(如 if、for、函数体)内部有效,外部无法访问; - 「无变量提升」:必须先声明后使用,否则报错(暂时性死区);
- 「不可重复声明」:同一作用域内不能重复声明同一变量。
示例
// 1. 块级作用域示例
if (true) {
let age = 20;
console.log(age); // 20(块内可访问)
}
console.log(age); // ReferenceError(块外不可访问)
// 2. 对比var的变量提升
console.log(varName); // undefined(var会提升)
var varName = "hello";
console.log(letName); // ReferenceError(let无提升,暂时性死区)
let letName = "world";
// 3. 不可重复声明
let num = 10;
let num = 20; // SyntaxError(重复声明报错)
- 使用场景:需要「变量值可修改」且「作用域隔离」的场景,如 for 循环计数器、临时变量。
2. const:块级作用域的常量
-
特性说明:
- 「块级作用域」:与
let一致,仅在块内有效; - 「声明即初始化」:必须在声明时赋值,否则报错;
- 「值不可修改?」:
- 基本类型(Number、String、Boolean 等):值不可修改;
- 引用类型(Object、Array、Function 等):引用地址不可修改,但内部属性 / 元素可修改。
示例
// 1. 基本类型:值不可修改
const PI = 3.14159;
PI = 3.14; // TypeError(基本类型值不可改)
// 2. 引用类型:内部可修改,地址不可改
const user = { name: "张三" };
user.name = "李四"; // 正常执行(修改内部属性)
user = { name: "王五" }; // TypeError(修改引用地址报错)
const arr = [1, 2, 3];
arr.push(4); // 正常执行(添加元素)
arr = [5, 6, 7]; // TypeError(修改引用地址报错)
- 使用场景:需要「值不可变」或「引用不可变」的场景,如配置项(PI、接口地址)、固定引用的对象 / 数组。
二、函数简化:箭头函数(Arrow Function)—— 告别繁琐的 function
箭头函数是 ES6 中最常用的语法糖之一,它不仅简化了函数的声明语法,更解决了「this 绑定混乱」的核心问题。
特性说明
- 「语法简化」:省略
function关键字,用=>连接参数和函数体; - 「this 绑定固定」:箭头函数没有自己的
this,它的this继承自「外层作用域的 this」(即声明时的 this,而非调用时的 this); - 「无 arguments 对象」:无法通过
arguments获取参数列表,需用「剩余参数」替代; - 「不能作为构造函数」:不能用
new关键字调用,否则报错。
示例
// 1. 基本语法:无参数 + 单语句(可省略{}和return)
const sayHi = () => console.log("Hi!");
sayHi(); // Hi!
// 2. 单个参数:可省略()
const double = num => num * 2;
console.log(double(5)); // 10
// 3. 多个参数:必须加()
const add = (a, b) => a + b;
console.log(add(3, 4)); // 7
// 4. 多语句函数体:需加{}和return
const calculate = (a, b) => {
const sum = a + b;
const product = a * b;
return sum + product; // 必须显式return
};
console.log(calculate(2, 3)); // 2+3 + 2*3 = 11
// 5. this绑定对比:解决传统函数的this问题
const user = {
name: "张三",
// 传统函数:this指向调用者(user)
sayName1: function() {
setTimeout(function() {
console.log(this.name); // undefined(this指向window/global)
}, 100);
},
// 箭头函数:this继承外层作用域(user)
sayName2: function() {
setTimeout(() => {
console.log(this.name); // 张三(正确)
}, 100);
}
};
user.sayName1(); // undefined
user.sayName2(); // 张三
使用场景
- 「简单回调函数」:如数组方法
map、filter、forEach的回调; - 「需要固定 this 的场景」:如异步操作(setTimeout、Promise)中的回调,避免 this 指向混乱;
- 「短逻辑函数」:如工具函数(计算、格式化),语法更简洁。
三、字符串优化:模板字符串(Template Literals)—— 终结字符串拼接地狱
ES6 之前,拼接字符串需要用+连接,遇到多行字符串或变量插值时,代码冗长且易出错。模板字符串用反引号(`)包裹,彻底解决了这些问题。
特性说明
- 「多行字符串」:直接换行即可,无需
\n或+; - 「变量 / 表达式插值」:用
${}包裹变量或表达式,自动解析并拼接; - 「标签模板」:可通过函数自定义模板字符串的解析逻辑(进阶用法)。
示例
// 1. 多行字符串:直接换行
const html = `
<div class="user">
<h1>用户信息</h1>
<p>姓名:张三</p>
</div>
`;
console.log(html); // 输出带换行的完整HTML字符串
// 2. 变量插值:${}包裹变量
const name = "张三";
const age = 25;
const info = `我叫${name},今年${age}岁`;
console.log(info); // 我叫张三,今年25岁
// 3. 表达式插值:${}内可写任意表达式
const a = 10;
const b = 20;
const calc = `${a} + ${b} = ${a + b}`;
console.log(calc); // 10 + 20 = 30
// 4. 标签模板(进阶):自定义解析逻辑
function format(strings, ...values) {
// strings:模板字符串的静态部分数组
// values:插值部分的数组
return strings[0] + values[0].toUpperCase() + strings[1];
}
const result = format`Hello, ${name}!`;
console.log(result); // Hello, 张三!(若name是小写,会转为大写)
使用场景
- 「拼接 HTML/JSON 字符串」:避免多行拼接的繁琐;
- 「动态生成文本」:如用户信息、日志、提示语;
- 「复杂字符串格式化」:结合标签模板实现自定义逻辑(如转义、国际化)。
四、数据提取:解构赋值(Destructuring Assignment)—— 简化变量赋值
解构赋值允许从数组或对象中「批量提取数据」,并直接赋值给变量,避免了重复的 “属性访问” 代码(如obj.a、obj.b)。
1. 数组解构:按位置匹配
- 特性:根据数组的「索引位置」匹配变量,支持默认值、嵌套解构。
示例
// 1. 基本数组解构
const [a, b, c] = [10, 20, 30];
console.log(a); // 10(索引0)
console.log(b); // 20(索引1)
console.log(c); // 30(索引2)
// 2. 跳过元素:用空逗号占位
const [x, , y] = [1, 2, 3];
console.log(x); // 1(索引0)
console.log(y); // 3(索引2,跳过索引1)
// 3. 默认值:当解构的值为undefined时使用默认值
const [m, n = 5] = [3]; // n未匹配到值,用默认值5
console.log(m); // 3
console.log(n); // 5
// 4. 嵌套数组解构
const [p, [q, r]] = [1, [2, 3]];
console.log(p); // 1
console.log(q); // 2
console.log(r); // 3
// 5. 与扩展运算符结合:获取剩余元素
const [first, ...rest] = [1, 2, 3, 4];
console.log(first); // 1
console.log(rest); // [2, 3, 4](剩余元素组成数组)
2. 对象解构:按属性名匹配
- 特性:根据对象的「属性名」匹配变量,支持别名、默认值、嵌套解构。
示例
// 1. 基本对象解构
const user = { name: "张三", age: 25 };
const { name, age } = user; // 变量名必须与属性名一致
console.log(name); // 张三
console.log(age); // 25
// 2. 别名:变量名与属性名不同时,用“属性名: 别名”
const { name: userName, age: userAge } = user;
console.log(userName); // 张三
console.log(userAge); // 25
// 3. 默认值:属性不存在或为undefined时使用默认值
const { gender = "男" } = user; // user没有gender属性,用默认值
console.log(gender); // 男
// 4. 嵌套对象解构
const userWithAddr = {
name: "张三",
addr: { province: "广东", city: "深圳" }
};
const { addr: { city } } = userWithAddr;
console.log(city); // 深圳
// 5. 函数参数解构:直接在参数中解构对象
function printUser({ name, age }) {
console.log(`姓名:${name},年龄:${age}`);
}
printUser(user); // 姓名:张三,年龄:25
使用场景
- 「提取对象属性」:如从接口返回的 JSON 数据中提取关键字段;
- 「函数参数简化」:当函数参数是对象时,直接解构获取所需属性,避免
obj.xxx的重复书写; - 「数组数据拆分」:如拆分函数返回的多个值(如
const [data, err] = await fetchData())。
五、数组 / 对象扩展:扩展运算符(...)—— 简化数据操作
扩展运算符(...)可以将「可迭代对象」(数组、Set、字符串等)或「对象」展开为单个元素 / 属性,常用于数组拷贝、合并,对象拷贝、合并等场景。
1. 数组扩展
- 特性:将数组展开为逗号分隔的元素列表,支持拷贝、合并、函数传参。
示例
// 1. 数组拷贝:创建新数组(浅拷贝)
const arr1 = [1, 2, 3];
const arr2 = [...arr1]; // 等价于arr1.slice()
arr2.push(4);
console.log(arr1); // [1, 2, 3](原数组不变)
console.log(arr2); // [1, 2, 3, 4]
// 2. 数组合并:替代concat方法
const arr3 = [4, 5, 6];
const mergedArr = [...arr1, ...arr3]; // 合并arr1和arr3
console.log(mergedArr); // [1, 2, 3, 4, 5, 6]
// 3. 函数传参:将数组展开为函数参数
function add(a, b, c) {
return a + b + c;
}
const nums = [1, 2, 3];
console.log(add(...nums)); // 6(等价于add(1, 2, 3))
// 4. 与解构结合:获取剩余元素(见解构赋值部分)
2. 对象扩展
- 特性:将对象展开为键值对列表,支持对象拷贝、合并、添加新属性。
示例
// 1. 对象拷贝:创建新对象(浅拷贝)
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1 }; // 等价于Object.assign({}, obj1)
obj2.c = 3;
console.log(obj1); // { a: 1, b: 2 }(原对象不变)
console.log(obj2); // { a: 1, b: 2, c: 3 }
// 2. 对象合并:后面对象的属性会覆盖前面的
const obj3 = { b: 3, d: 4 };
const mergedObj = { ...obj1, ...obj3 };
console.log(mergedObj); // { a: 1, b: 3, d: 4 }(obj3的b覆盖obj1的b)
// 3. 添加新属性:合并时新增属性
const newObj = { ...obj1, c: 3, a: 10 }; // 新增c,修改a
console.log(newObj); // { a: 10, b: 2, c: 3 }
使用场景
- 「数组操作」:拷贝数组、合并数组、向函数传递数组参数;
- 「对象操作」:拷贝对象、合并对象、添加 / 修改对象属性(如 React 中的 state 更新);
- 「组件开发」:如 React 组件传递 props 时,批量传递属性(
<Child {...props} />)。
六、函数参数增强:默认参数 + 剩余参数
ES6 对函数参数进行了两大优化:「默认参数」允许直接设置参数默认值,「剩余参数」允许收集不定数量的参数,替代了繁琐的arguments对象。
1. 默认参数(Default Parameters)
- 特性:在函数声明时直接为参数设置默认值,当参数未传递或为
undefined时生效。
示例
// 1. 基本默认参数
function greet(name = "陌生人") {
console.log(`你好,${name}!`);
}
greet(); // 你好,陌生人!(未传参数,用默认值)
greet("张三"); // 你好,张三!(传参数,覆盖默认值)
// 2. 默认参数与解构结合
function printUser({ name = "未知", age = 0 } = {}) {
// 注意:参数默认值设为{},避免未传参数时解构报错
console.log(`姓名:${name},年龄:${age}`);
}
printUser(); // 姓名:未知,年龄:0(未传参数)
printUser({ name: "李四" }); // 姓名:李四,年龄:0(age未传,用默认值)
// 3. 默认参数的顺序:默认参数应放在非默认参数之后
function add(a, b = 0) { // 正确:非默认参数在前
return a + b;
}
// function add(a = 0, b) { // 不推荐:默认参数在前,调用时易混淆
// return a + b;
// }
2. 剩余参数(Rest Parameters)
- 特性:用
...rest表示,收集函数的「剩余参数」并组成一个数组,替代arguments(arguments是类数组,需转换为数组才能用数组方法)。
示例
// 1. 收集所有剩余参数
function sum(...nums) {
// nums是数组,可直接用数组方法reduce
return nums.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(4, 5, 6, 7)); // 22
// 2. 收集部分剩余参数
function printFirstAndRest(first, ...rest) {
console.log("第一个参数:", first);
console.log("剩余参数:", rest);
}
printFirstAndRest(1, 2, 3, 4);
// 第一个参数:1
// 剩余参数:[2, 3, 4]
// 3. 对比arguments:剩余参数是数组,arguments是类数组
function compareArgs(...rest) {
console.log(rest instanceof Array); // true(数组)
console.log(arguments instanceof Array); // false(类数组)
// arguments需转换为数组才能用reduce:Array.from(arguments).reduce(...)
}
compareArgs(1, 2, 3);
使用场景
- 「默认参数」:函数参数有固定默认值的场景(如分页查询的
pageSize=10); - 「剩余参数」:函数需要接收不定数量参数的场景(如计算总和、批量处理数据)。
七、面向对象:Class—— 语法糖封装原型继承
ES6 之前,JavaScript 通过「原型链」实现继承,语法繁琐且不直观;ES6 的class是「原型继承的语法糖」,让代码更接近传统面向对象语言(如 Java、Python)的写法,降低了学习成本。
特性说明
- 「类定义」:用
class关键字定义类,内部包含constructor(构造函数)和方法; - 「继承」:用
extends关键字实现类的继承,super()调用父类构造函数; - 「静态方法」:用
static关键字定义静态方法,只能通过类调用,不能通过实例调用; - 「实例方法」:类内部定义的方法,只能通过实例调用。
// 1. 定义基础类
class Person {
// 构造函数:实例化时执行,初始化属性
constructor(name, age) {
this.name = name; // 实例属性
this.age = age;
}
// 实例方法:通过实例调用
sayHi() {
console.log(`我叫${this.name},今年${this.age}岁`);
}
// 静态方法:通过类调用,this指向类本身
static createPerson(name, age) {
return new Person(name, age); // 工厂方法,创建Person实例
}
}
// 实例化类
const person1 = new Person("张三", 25);
person1.sayHi(); // 我叫张三,今年25岁(调用实例方法)
// 调用静态方法
const person2 = Person.createPerson("李四", 30);
person2.sayHi(); // 我叫李四,今年30岁
// 2. 继承:定义子类Student继承自Person
class Student extends Person {
// 子类构造函数:必须调用super()
constructor(name, age, studentId) {
super(name, age); // 调用父类构造函数,初始化name和age
this.studentId = studentId; // 子类新增属性
}
// 子类重写父类方法
sayHi() {
console.log(`我是学生${this.name},学号${this.studentId}`);
}
// 子类新增方法
study() {
console.log(`${this.name}正在学习`);
}
}
// 实例化子类
const student1 = new Student("王五", 20, "2024001");
student1.sayHi(); // 我是学生王五,学号2024001(重写后的方法)
student1.study(); // 王五正在学习(子类新增方法)
console.log(student1 instanceof Student); // true
console.log(student1 instanceof Person); // true(子类实例也是父类实例)
使用场景
- 「创建多个相似实例」:如用户、商品、订单等具有统一属性和方法的对象;
- 「代码复用与继承」:如基础类(Person)和子类(Student、Teacher),复用基础属性和方法;
- 「框架开发」:如 React 组件(class 组件)、Vue 组件(Options API 的底层基于类思想)。
八、模块化:import /export—— 原生支持模块化开发
ES6 之前,JavaScript 没有原生模块化方案,只能依赖 AMD(RequireJS)、CMD(SeaJS)等第三方库;ES6 的import/export让模块化成为语言原生特性,规范了代码的拆分与复用。
核心概念
- 模块(Module):一个 JS 文件就是一个模块,内部变量 / 函数默认对外不可见;
- 导出(Export):将模块内的变量 / 函数暴露给外部,分为「命名导出」和「默认导出」;
- 导入(Import):在其他模块中引入已导出的变量 / 函数。
语法示例
1. 命名导出(Named Export):导出多个成员
// 模块A:moduleA.js
// 方式1:声明时直接导出
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
// 方式2:集中导出(推荐,清晰可见)
const multiply = (a, b) => a * b;
const subtract = (a, b) => a - b;
export { multiply, subtract };
// 导出时重命名:用“原名称 as 新名称”
export { multiply as multiplyFn };
2. 默认导出(Default Export):导出单个成员
一个模块只能有一个默认导出,常用于导出一个类、函数或对象。
// 模块B:moduleB.js
// 方式1:直接导出默认值
export default class Person {
constructor(name) {
this.name = name;
}
}
// 方式2:先定义后导出(推荐)
const greet = (name) => `Hello, ${name}`;
export default greet;
3. 导入(Import):引入其他模块的成员
// 导入命名导出的成员
import { PI, add, multiply as multiplyFn } from './moduleA.js';
console.log(PI); // 3.14159
console.log(add(1, 2)); // 3
console.log(multiplyFn(3, 4)); // 12
// 导入所有命名导出的成员,用* as 别名
import * as moduleA from './moduleA.js';
console.log(moduleA.PI); // 3.14159
console.log(moduleA.subtract(5, 2)); // 3
// 导入默认导出的成员:无需{},可自定义名称
import Person from './moduleB.js'; // 导入默认类
const person = new Person("张三");
console.log(person.name); // 张三
import myGreet from './moduleB.js'; // 导入默认函数,自定义名称myGreet
console.log(myGreet("李四")); // Hello, 李四
// 同时导入默认导出和命名导出
import greet, { PI } from './moduleA.js'; // 假设moduleA有默认导出greet
使用场景
- 「项目拆分」:将大型项目拆分为多个模块(如工具模块、组件模块、接口模块);
- 「代码复用」:在多个文件中复用工具函数、类、配置项;
- 「第三方库引入」:如引入 React(
import React from 'react')、Vue 等库。
九、新数据结构:Set / Map—— 解决传统数组 / 对象的痛点
ES6 引入了两种新的内置数据结构:Set(无重复值的集合)和Map(键可以是任意类型的字典),弥补了传统数组(无法快速去重)和对象(键只能是字符串 / Symbol)的不足。
1. Set:无重复值的集合
-
特性:
-
存储「唯一值」:自动去重,不允许重复元素;
-
可迭代:支持
for...of遍历,可转换为数组; -
常用方法:
add()(添加)、delete()(删除)、has()(判断是否存在)、size(获取长度)、clear()(清空)。
-
示例
// 1. 创建Set:传入可迭代对象(如数组)
const set1 = new Set([1, 2, 3, 3]); // 自动去重
console.log(set1); // Set(3) {1, 2, 3}
console.log(set1.size); // 3(长度)
// 2. 基本操作
set1.add(4); // 添加元素
console.log(set1); // Set(4) {1, 2, 3, 4}
set1.delete(2); // 删除元素
console.log(set1); // Set(3) {1, 3, 4}
console.log(set1.has(3)); // true(元素存在)
console.log(set1.has(5)); // false(元素不存在)
// set1.clear(); // 清空Set
// 3. 遍历Set
for (const item of set1) {
console.log(item); // 1, 3, 4
}
// 4. 转换为数组(常用:数组去重)
const arr = [1, 2, 2, 3];
const uniqueArr = [...new Set(arr)]; // 去重
console.log(uniqueArr); // [1, 2, 3]
2. Map:键值对集合(键可任意类型)
-
特性:
- 键可以是「任意类型」:如 Number、String、Object、Symbol 等(对象的键只能是字符串 / Symbol);
- 可迭代:支持
for...of遍历,按插入顺序排列; - 常用方法:
set(key, value)(添加键值对)、get(key)(获取值)、delete(key)(删除)、has(key)(判断)、size(长度)、clear()(清空)。
示例
// 1. 创建Map
const map1 = new Map();
// 2. 添加键值对(键可以是任意类型)
const objKey = { id: 1 };
map1.set("name", "张三"); // 字符串键
map1.set(25, "年龄"); // 数字键
map1.set(objKey, "用户对象"); // 对象键
map1.set(Symbol("id"), 1001); // Symbol键
console.log(map1.size); // 4(长度)
// 3. 获取值
console.log(map1.get("name")); // 张三
console.log(map1.get(objKey)); // 用户对象
console.log(map1.get(Symbol("id"))); // undefined(Symbol是唯一的,新创建的Symbol与原键不同)
// 4. 判断键是否存在
console.log(map1.has("name")); // true
// 5. 遍历Map
// 方式1:遍历键值对
for (const [key, value] of map1) {
console.log(`${key}: ${value}`);
}
// 方式2:遍历键
for (const key of map1.keys()) {
console.log(key);
}
// 方式3:遍历值
for (const value of map1.values()) {
console.log(value);
}
// 6. 转换为数组
const mapArr = [...map1];
console.log(mapArr); // [["name", "张三"], [25, "年龄"], [{id:1}, "用户对象"], [Symbol(id), 1001]]
使用场景
- Set:数组去重、存储不重复的 ID 列表、判断元素是否存在(比数组
indexOf效率高); - Map:存储键值对且键不是字符串的场景(如用对象作为键)、需要保持插入顺序的键值对(对象的键在 ES6 前不保证顺序)。
十、异步编程:Promise—— 解决回调地狱
ES6 之前,异步操作(如 AJAX、定时器)依赖回调函数,多个异步操作嵌套时会形成「回调地狱」(代码层级深、可读性差、难以维护)。Promise 是一种「异步编程方案」,用链式调用替代回调嵌套,让异步流程更清晰。
核心概念
- 三种状态:
pending:初始状态,既未成功也未失败;fulfilled:操作成功,状态不可逆;rejected:操作失败,状态不可逆。
- 两个方法:
then():状态变为fulfilled时执行,返回新的 Promise,支持链式调用;catch():状态变为rejected时执行,捕获错误(包括then中的错误)。
示例
// 1. 创建Promise
function fetchData() {
return new Promise((resolve, reject) => {
// 模拟异步操作(如AJAX请求)
setTimeout(() => {
const success = true; // 模拟成功/失败
if (success) {
const data = { name: "张三", age: 25 };
resolve(data); // 成功:调用resolve,状态变为fulfilled
} else {
const error = new Error("数据获取失败");
reject(error); // 失败:调用reject,状态变为rejected
}
}, 1000);
});
}
// 2. 使用Promise:链式调用
fetchData()
.then((data) => {
console.log("获取数据成功:", data);
// 返回新的Promise,继续链式调用
return new Promise((resolve) => {
setTimeout(() => {
resolve(data.name); // 将name传递给下一个then
}, 500);
});
})
.then((name) => {
console.log("处理后的数据:", name); // 张三
})
.catch((error) => {
console.log("错误:", error.message); // 捕获所有前面的错误
})
.finally(() => {
console.log("无论成功或失败,都会执行"); // 可选,用于清理操作(如关闭加载动画)
});
// 3. Promise常用静态方法
// 3.1 Promise.all():同时执行多个Promise,全部成功才返回,有一个失败则立即失败
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
Promise.all([promise1, promise2])
.then((values) => {
console.log(values); // [1, 2](所有成功,返回结果数组)
})
.catch((error) => {
console.log(error);
});
// 3.2 Promise.race():同时执行多个Promise,第一个改变状态的Promise决定结果
const promise3 = new Promise((resolve) => setTimeout(resolve, 100, "快的Promise"));
const promise4 = new Promise((resolve) => setTimeout(resolve, 200, "慢的Promise"));
Promise.race([promise3, promise4])
.then((value) => {
console.log(value); // "快的Promise"(第一个成功的结果)
});
使用场景
- 「单个异步操作」:如 AJAX 请求、文件读取,用
then处理成功,catch处理错误; - 「多个异步操作」:
- 需全部成功:用
Promise.all()(如同时获取多个接口数据); - 只需第一个结果:用
Promise.race()(如设置请求超时时间);
- 需全部成功:用
- 「异步流程控制」:替代回调嵌套,让多个异步操作按顺序执行(链式调用)。
十一、其他实用特性
除了上述核心特性,ES6 还有一些常用的小特性,同样能提升开发效率。
1. for...of 循环:遍历可迭代对象
- 特性:遍历「可迭代对象」(数组、Set、Map、字符串、Generator 等),直接获取「值」(区别于
for...in获取「索引 / 键」),支持break/continue。
示例
// 遍历数组
const arr = [1, 2, 3];
for (const value of arr) {
if (value === 2) break;
console.log(value); // 1
}
// 遍历Set
const set = new Set([1, 2, 3]);
for (const value of set) {
console.log(value); // 1, 2, 3
}
// 遍历Map
const map = new Map([["name", "张三"], ["age", 25]]);
for (const [key, value] of map) {
console.log(`${key}: ${value}`); // name: 张三, age: 25
}
2. Symbol:唯一不可变的值
- 特性:
- 「唯一」:每个 Symbol 都是唯一的,即使描述相同;
- 「不可变」:创建后无法修改;
- 「用途」:作为对象属性名(避免属性名冲突)、定义常量。
示例
// 创建Symbol
const sym1 = Symbol();
const sym2 = Symbol("描述"); // 描述仅用于调试,不影响唯一性
// 唯一性:即使描述相同,也是不同的Symbol
const sym3 = Symbol("test");
const sym4 = Symbol("test");
console.log(sym3 === sym4); // false
// 作为对象属性名(避免冲突)
const obj = {
[sym2]: "Symbol属性值", // 必须用[]包裹
name: "张三"
};
console.log(obj[sym2]); // Symbol属性值(只能通过Symbol访问)
3. 数组方法扩展:Array.from () + Array.of ()
- Array.from():将「类数组对象」(如
arguments、DOM 集合)或「可迭代对象」(如 Set)转为数组。
const domNodes = document.querySelectorAll("div"); // DOM集合(类数组)
const arrNodes = Array.from(domNodes); // 转为数组
- Array.of():创建数组,解决
new Array()的歧义(new Array(3)是长度为 3 的空数组,Array.of(3)是[3])。
console.log(Array.of(1, 2, 3)); // [1, 2, 3]
console.log(Array.of(5)); // [5]
总结:ES6 为何重要?
ES6 不仅是一次语法更新,更是 JavaScript 语言的「现代化转型」:
- 解决历史痛点:
let/const解决作用域问题,Promise解决回调地狱,import/export规范模块化; - 提升开发效率:箭头函数、模板字符串、解构赋值等语法糖简化代码,减少冗余;
- 支撑现代框架:React、Vue、Angular 等框架的核心语法(如组件、 hooks、模块化)均依赖 ES6 特性;
- 扩展语言能力:
Class、Set/Map、Symbol等特性让 JavaScript 能应对更复杂的开发场景(如大型应用、跨端开发)。
更多推荐


所有评论(0)