第 11 章 · ES6+ 与现代 JavaScript
本章目标:掌握 ES6 及之后的核心语法——解构、展开、模板字符串、箭头函数、模块概念、Map/Set,并用现代写法重构 academy-demo 中的课程数据与 Todo 状态逻辑。
前置:第 8~10 章;浏览器需支持 ES2015+(近五年主流浏览器均可)。
11.1 为什么学 ES6+
| 维度 | ES5 写法 | ES6+ 写法 | 收益 |
|---|
| 变量 | var 函数作用域 | const / let 块级作用域 | 减少变量提升 bug |
| 字符串 | 'Hello ' + name | 模板字符串 | 可读性、多行 |
| 函数 | function(){} | 箭头函数 | 简洁回调 |
| 对象 | 手动合并属性 | 展开运算符 | 不可变更新 |
| 模块 | 全局变量 / IIFE | import / export | 命名空间清晰 |
行业案例 · 贤紫优选商城:管理后台 2019 年仍为 ES5 + jQuery 打包单体 800KB;迁移到 ES6 模块 + Tree Shaking 后,首屏 JS 降至 220KB,构建时间从 90s 降至 12s。
11.2 模板字符串
const course = { id: 'fe-11', title: 'ES6+ 与现代 JavaScript', hours: 5 };
const label = `课程「${course.title}」共 ${course.hours} 课时,slug: fe-${course.id.split('-')[1]}`;
const multiline = `
<article class="course-card">
<h3>${course.title}</h3>
</article>
`;
| 特性 | 语法 | 注意 |
|---|
| 插值 | ${expression} | 表达式内可调用函数 |
| 多行 | 反引号内直接换行 | 注意缩进空白会保留 |
| 标签模板 | ` tag... ` | 高级场景(样式库) |
安全提醒:模板字符串插入用户输入前必须转义(见第 9 章 escapeHtml)。
11.3 解构赋值
11.3.1 数组解构
const rgb = [200, 24, 91];
const [r, g, b] = rgb;
const [first, , third] = ['HTML', 'CSS', 'JS'];
// 交换变量
let a = 1, b = 2;
[a, b] = [b, a];
// 剩余参数
const [head, ...rest] = [1, 2, 3, 4]; // head=1, rest=[2,3,4]
11.3.2 对象解构
const course = {
id: 'fe-11',
title: 'ES6+',
meta: { level: 'intermediate', free: false },
};
const { title, id: courseId } = course; // 重命名 id → courseId
const { meta: { level } } = course; // 嵌套解构
function renderCourse({ title, hours = 4 }) {
return `${title}(${hours}h)`;
}
// 函数参数默认值 + 解构
renderCourse({ title: 'DOM', hours: 3 });
| 场景 | 写法 | academy-demo 用途 |
|---|
| 取 API 字段 | const { data } = await res.json() | 课程列表 |
| 配置对象 | const { theme = 'light' } = options | 主题初始化 |
| 交换/忽略 | const [, second] = arr | 排行榜第二名 |
11.4 展开运算符(Spread)与剩余(Rest)
const baseTags = ['HTML', 'CSS'];
const allTags = [...baseTags, 'JavaScript', 'Vite'];
const defaults = { theme: 'light', locale: 'zh-CN' };
const userPrefs = { theme: 'dark' };
const settings = { ...defaults, ...userPrefs }; // theme 被覆盖为 dark
// 不可变更新 Todo(React 思维的前置)
function toggleTodoImmutable(todos, id) {
return todos.map(t =>
t.id === id ? { ...t, done: !t.done } : t
);
}
// Rest 参数
function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}
| 运算符 | 位置 | 含义 |
|---|
...arr | 数组/对象字面量中 | 展开元素 |
...obj | 对象字面量中 | 浅拷贝属性 |
...args | 函数参数末尾 | 收集剩余参数 |
注意:展开是浅拷贝,嵌套对象仍共享引用。
11.5 箭头函数
// 传统
const double = function (n) { return n * 2; };
// 箭头
const double = n => n * 2;
const courses = list.filter(c => c.free);
const sorted = [...list].sort((a, b) => a.hours - b.hours);
document.querySelector('#btn').addEventListener('click', () => {
console.log('clicked');
});
| 对比项 | 普通函数 | 箭头函数 |
|---|
this | 动态绑定 | 词法继承外层 |
arguments | 有 | 无,用 Rest |
new | 可作构造函数 | 不可 |
| 适用 | 对象方法、构造函数 | 回调、数组方法 |
// 对象方法仍推荐简写,不用箭头(避免 this 问题)
const store = {
items: [],
add(item) { this.items.push(item); }, // ✓
// add: (item) => this.items.push(item) // ✗ this 不是 store
};
11.6 其他常用 ES6+ 语法