README
# 卷二 · 综合案例总导读(4 案例精品版)
本卷是**卷一《基础入门》**的配套实战篇。学完卷一 15 章基础语法后,通过 4 个层层递进的精品案例把散落的知识点串起来,形成 "能独立写浏览器/Node 项目" 的能力。
其中第 4 个
jschart(响应式数据看板) 是 "集大成的毕业设计",一篇覆盖卷一全部 15 章。
# 01.定位与使用方式
本卷的每一篇都按 "照着写 · 抄得懂 · 改得动" 三个层次设计:
- 照着写:每个小节先给需求、再给代码片段,初学者跟着键入即可在浏览器跑通——所有代码均按"小白手把手"的步骤拆解,一步一步写、一步一步测。
- 抄得懂:代码后必有 "为什么这样写 / 关键机制原理 / 新手陷阱" 小节,回答 "JS 为什么不能像 Java/Python 那样随手写"。
- 改得动:每篇结尾留 3-5 个 "延伸挑战",鼓励读者用新学的特性重构。
代码标准:以 ECMAScript 2022(ES13) 为基线,兼容 ES2023/2024 新特性(会明确标注);运行环境以 现代浏览器(Chrome ≥ 110 / Firefox ≥ 110 / Safari ≥ 16) 为主,部分案例使用 Node.js ≥ 18 做工具脚本;构建仅依赖 原生 ES Module + Vite 5(仅 04 引入 Vite 做开发服务器)。
零库约束:本卷坚持 不引入运行时第三方库(不用 jQuery / Lodash / Vue / React / ECharts / Axios),全部用原生 JS + Web Platform API 实现。让读者亲眼看到 Vue 的响应式、ECharts 的渲染、Axios 的拦截器是怎么从原生 API 演化来的。
学习方式:建议每个案例独立创建一个目录,跟着教程边读边写——看一段、敲一段、跑一段。完成一个案例约需 5-16 小时(按难度递增),全部 4 个案例预计 43 小时完成。
为什么是 4 个案例而不是 8 个? 卷二的设计哲学是 "少而精":① JS 的核心难点高度集中在 DOM/事件、异步、Web 平台 API、响应式 四大块,每块用一个独立案例承载即可;② 4 案例之间存在严格的 "技术依赖链"——后一个必复用前一个的产物,避免重复造轮子;③ 第 04 案例
jschart一篇打满 15 章,是真正的毕业设计。
# 02.4 案例总览
难度阶梯:
⭐⭐ → ⭐⭐⭐⭐ → ⭐⭐⭐⭐ → ⭐⭐⭐⭐⭐
01 jstodo → 02 jsfeed → 03 jsplayer → 04 jschart
──────────── ───────────── ───────────── ─────────────
浏览器交互入门 异步流水线 Web 平台 API 响应式 + 全栈集成
单页 ~800 行 多模块 ~1500 行 多模块 ~2000 行 完整工程 ~3500 行
2
3
4
5
6
7
| # | 案例 | 难度 | 时长 | 字数 | 主导领域 |
|---|---|---|---|---|---|
| 01 | 待办清单事件驱动 | ⭐⭐ | 5 h | ~1.5 万 | DOM / 事件委托 / ESM / 命令模式 |
| 02 | 异步订阅流式解析 | ⭐⭐⭐⭐ | 10 h | ~2 万 | Promise / fetch / 生成器 / 流式 |
| 03 | 视频播放器自实现 | ⭐⭐⭐⭐ | 12 h | ~2 万 | MSE / 视频流 / Canvas / Web API |
| 04 | 图表看板全栈开发 🎓 | ⭐⭐⭐⭐⭐ | 16 h | ~2.5 万 | Proxy 响应式 / Canvas / WebSocket / Worker(毕业设计) |
核心特点:第 04 案例复用前 3 个的产物——用 01 的 DOM 渲染做配置面板、用 02 的异步流水线做数据拉取、用 03 的 Canvas + 高频渲染做图表引擎。形成 "积木拼装" 的工程闭环。
# 03.卷一章节—案例覆盖矩阵
下表展示卷一每章在本卷的落地点。读者也可以反向使用——"我想练习生成器,去找第 02 案例"。
✅ = 该章节是案例的核心知识点 / 🟡 = 顺带使用 / 空白 = 不涉及
| 卷一章节 | 核心知识点 | 01 jstodo | 02 jsfeed | 03 jsplayer | 04 jschart |
|---|---|---|---|---|---|
| 01 入门介绍 | 引入方式 / 严格模式 | ✅ | 🟡 | 🟡 | 🟡 |
| 02 数据类型 | Object / Map / WeakMap / Set | ✅ | ✅ | ✅ | ✅ |
| 03 运算符 | ?? / ?. / 解构 / 扩展 | ✅ | ✅ | ✅ | ✅ |
| 04 函数 | 闭包 / 高阶函数 / 箭头函数 | ✅ | ✅ | ✅ | ✅ |
| 05 面向对象 | class / extends / 私有字段 # | ✅ | 🟡 | ✅ | ✅ |
| 06 标准库 | Date / Math / JSON / URL | 🟡 | ✅ | ✅ | ✅ |
| 07 异步操作 | Promise / async-await / 事件循环 | 🟡 | ✅ | ✅ | ✅ |
| 08 事件设计 | 事件冒泡 / 委托 / EventTarget | ✅ | 🟡 | ✅ | ✅ |
| 09 错误机制 | Error 继承 / AggregateError | ✅ | ✅ | ✅ | ✅ |
| 10 模块开发 | ESM / 动态 import() | ✅ | ✅ | ✅ | ✅ |
| 11 字符串 | 模板字符串 / 正则 / Intl | ✅ | ✅ | 🟡 | ✅ |
| 12 迭代器与生成器 | Symbol.iterator / async function* | 🟡 | ✅ | 🟡 | ✅ |
| 13 Symbol | 唯一标识 / 元编程 / Well-known | 🟡 | 🟡 | 🟡 | ✅ |
| 14 DOM 操作 | createElement / MutationObserver | ✅ | ✅ | ✅ | ✅ |
| 15 网络请求 | fetch / WebSocket / AbortController | 🟡 | ✅ | ✅ | ✅ |
结论:卷一 15 章每一章都至少被 ✅ 标记 1 次以上;核心章节(02 数据类型 / 04 函数 / 07 异步 / 14 DOM)被 4 个案例全面夯实;第 04 案例 jschart 一篇打满 15 章——这就是 "毕业设计" 的含义。
# 04.单案例知识点详图
# 案例 01 · jstodo · 原生待办清单 ⭐⭐
学完卷一第 1-6、8-10、14 章后能立刻上手。从 "会写函数" 到 "会做交互应用" 的桥梁。纯原生 JS + ES Module,0 第三方库。
功能列表:
- 增删改查 todo、按标签 / 完成状态筛选、
localStorage本地持久化 - 拖拽排序、双击编辑、
Enter提交、Escape取消、批量操作 - 主题切换(明暗模式 CSS 变量)、多语言切换(手写迷你 i18n)
- 撤销 / 重做(命令模式 + 双栈)
- 键盘快捷键系统(vim 风格
j/k上下、g g跳顶)
JS 特性主线:
- 语法基础:模板字符串拼 HTML、解构赋值取 DOM 引用、可选链
?.防空、扩展运算符 immutable 更新数组 - 事件设计:事件委托(一个监听器绑在
<ul>上处理 N 个 todo 项)、自定义事件new CustomEvent('todo:added', { detail })、AbortController统一卸载所有监听器 - DOM 操作:
createElement高频更新 vsDocumentFragment批量插入的 benchmark 对比、手写最简版 DOM diff(key-based reconcile) - 模块化:拆
state.js / view.js / store.js / commands.js / shortcuts.js,MVC 雏形 - 面向对象:
class Command抽象基类(AddCommand/DeleteCommand/EditCommand),Symbol.iterator让TodoList可被for...of
反模式对照(精彩点):
- ❌
innerHTML = arr.map(...).join('')全量重渲染 → ✅ 增量 DOM diff - ❌ 每个 todo 节点单独绑
onclick→ ✅ 事件委托(讲清 "事件冒泡" 原理) - ❌
JSON.parse(localStorage.getItem('todos'))不防异常 → ✅ try/catch + schema 校验 + 默认值降级 - ❌ 全局变量散落 → ✅ ES Module 私有作用域 + 显式
export - ❌ 未卸载监听器导致内存泄漏 → ✅
AbortController统一管理生命周期
产出物:~800 行 JS + 200 行 CSS + index.html,零依赖,浏览器双击即可运行。
# 案例 02 · jsfeed · 异步 RSS 阅读器 ⭐⭐⭐⭐
覆盖卷一第 7、9、12、13、15 章的核心——异步、错误、生成器、Symbol、网络。JS 最难也是最有特色的部分 —— 异步、Promise、生成器、Stream 一锅炖。
功能列表:
- 输入 N 个 RSS 订阅源(
fetch拉 XML,DOMParser解析) - 并发拉取(
Promise.all全量 /Promise.allSettled容错 /Promise.race超时)三种策略对照 - 限流并发:手写
pLimit(5)(5 个一组),用纯 Promise + 队列实现,不依赖 p-limit 库 AbortController取消未完成请求(关闭面板 → 自动取消)- 流式处理:
response.body.getReader()边下载边解析(10MB 大 feed 不爆内存) - 生成器分页:
async function*实现 "无限滚动" - 离线缓存:失败时回落到
localStorage上次结果 - 错误重试:指数退避 + 熔断器(连续失败 3 次后打开熔断 30s)
JS 特性主线:
- 异步操作:回调地狱 → Promise → async/await 三代演进对照;事件循环(宏任务 vs 微任务)实操题(猜输出顺序)
- 网络请求:
fetch完整封装(拦截器、超时、重试)、AbortController取消、Headers/URLSearchParams - 迭代器与生成器:
async function*流式分页(核心难点!)、Symbol.asyncIterator自定义异步流 - 错误机制:自定义
NetworkError/ParseError/TimeoutError类继承Error、AggregateError聚合多源错误、错误边界设计(catch 应该放在哪一层) - 字符串 / 标准库:
URL对象、URLSearchParams、Date.toISOString时区处理、Intl.RelativeTimeFormat("3 分钟前") - 模块化:动态
import()按需加载解析器(rss / atom / json-feed 三种解析插件)
反模式对照(精彩点):
- ❌
arr.forEach(async ...)(不会等!)→ ✅for...of + await或Promise.all(arr.map(...)) - ❌
Promise.all一个失败全失败 → ✅Promise.allSettled部分容错 - ❌ 无限并发 fetch 把浏览器打死 → ✅
pLimit信号量(用 Promise + 队列手写) - ❌ 大文件
await response.json()卡死主线程 → ✅ 流式 reader 分块解析 - ❌
try/catch包不到setTimeout里的异常 → ✅ 全局unhandledrejection兜底 - ❌ 重试无退避导致雪崩 → ✅ 指数退避 + jitter
产出物:~1500 行 JS,10+ 模块文件,含一个手写 pLimit 库 + 3 种 feed 格式解析器 + 完整错误体系。
# 案例 03 · jsplayer · H5 视频播放器 ⭐⭐⭐⭐
覆盖卷一第 5、6、8、14、15 章的浏览器宿主能力——
class设计、Web 平台 API、事件、DOM、网络。这是 JS 区别于 C++/Go 的灵魂——浏览器宿主能力。
功能列表:
- 三层架构:媒体层(MSE 喂数据) / 控制层(播放/暂停/进度/音量/倍速 / 弹幕) / UI 层(自定义皮肤)
- MSE(Media Source Extensions):手动用
SourceBuffer.appendBuffer()喂分片,自己实现一个迷你 HLS / DASH(解析 m3u8 → 顺序拉 ts → 喂 MSE) - 进度条:缓冲区高亮(
buffered/played/seekable三个 TimeRanges 区分显示)、mousemove预览缩略图 - 弹幕系统:基于 Canvas 渲染(不污染 DOM 树),支持百万条弹幕的高性能调度(对象池 + 时间索引 + RAF)
- 快捷键 + 手势:空格暂停 / 左右箭头 ±5s / 上下箭头音量、移动端单双击 / 滑动手势
- Picture-in-Picture API(画中画)、Fullscreen API(全屏)、Media Session API(系统媒体控件)
- WebVTT 字幕:
<track>标签 + 自定义解析器(手写 VTT parser) - 网络层:
fetch分片下载 +AbortController切换清晰度时取消旧请求 + 连接复用 - 降级策略:原生
<video src=>→ MSE → HLS 软解(兼容 Safari 移动端)
JS 特性主线:
- 面向对象:
class Player extends EventTarget(继承原生 EventTarget 实现 on/off/emit)、私有字段#state/#mediaSource、组合优于继承(Player持有Loader/Renderer/DanmakuEngine实例) - 事件设计:原生
<video>共 24 个事件(loadedmetadata/timeupdate/waiting/seeking/ended...)的语义辨析、节流的timeupdate(每秒 4 次) vsrequestVideoFrameCallback(每帧) - DOM 操作:自定义
<custom-player>Web Component、Canvas 高频渲染(弹幕轨道 60 FPS)、MutationObserver监听容器尺寸变化、ResizeObserver配合dpr高清屏适配 - 网络请求:分片
fetch+Range请求头、ReadableStream流式喂 MSE、AbortController切换码率 - 标准库:
URL解析 m3u8 路径、Blob/Uint8Array/ArrayBuffer处理二进制、Math时间戳格式化 - 错误机制:媒体错误码(
MediaError.MEDIA_ERR_NETWORK/DECODE/SRC_NOT_SUPPORTED/ABORTED)映射 + 自动降级链
反模式对照(精彩点):
- ❌ 监听
timeupdate做高频 UI 更新(4 Hz 卡顿)→ ✅requestVideoFrameCallback(每帧精准回调) - ❌ 全屏用
el.requestFullscreen()忘记前缀 → ✅ 多前缀兼容 +fullscreenchange事件统一 - ❌ MSE
appendBuffer同步连续调用 → ✅ 队列化 +updateend等待(SourceBuffer 是有状态的) - ❌ 弹幕用 N 个
<div>+ CSS 动画 → ✅ Canvas 单画布 + RAF(性能 50 倍) - ❌ 切换清晰度时旧 fetch 不取消 → ✅
AbortController链式取消 - ❌ 移动端
playsinline缺失导致 iOS 全屏劫持 → ✅ 多平台属性矩阵
为什么需要这个案例(与 C++/Go 综合案例的差异化):
C++ 综合案例的灵魂是 OOP + 内存模型,Go 的灵魂是 并发 + 工程化,JS 的灵魂是 运行在浏览器宿主里的 Web 平台 API 大全。前端工程师 80% 的工作是 "驯服浏览器"——而视频播放器是一次性集中演练 MSE / Canvas / Fullscreen / PiP / WebVTT / Media Session / Range 请求 / Web Component / EventTarget / requestVideoFrameCallback 十大宿主 API 的最佳载体。
产出物:~2000 行 JS,可独立作为一个开源播放器组件发布;包含 m3u8 demo 视频源 + 一份"为什么不用 video.js"对照文档。
# 案例 04 · jschart · 响应式数据看板(毕业设计 🎓)⭐⭐⭐⭐⭐
集大成之作。复用 01 的 DOM 渲染 + 02 的异步流水线 + 03 的 Canvas 高频渲染,造一个迷你版 "Vue + ECharts + Devtools"。一篇覆盖全部 15 章。
功能列表:
- 响应式系统:手写 mini-vue(
Proxy拦截 +Reactive/Effect/Computed/Watch四件套) - 图表引擎:纯 Canvas 画折线 / 柱状 / 饼图 / 散点(不引 Chart.js / ECharts),数据变化自动重绘
- 数据源:WebSocket 实时推送 + REST 拉取 + IndexedDB 持久化,三源合一
- 看板配置:拖拽布局保存到 URL(
history.pushState),分享链接还原 - 插件系统:约定
Plugin协议接口,注册即用(导出 PNG / 导出 CSV / 全屏 / 数据筛选) - Web Worker:海量数据排序 / 过滤甩到 worker,主线程不卡
- 诊断面板:自带 "性能监视器"(FPS / effect 触发次数 / 网络耗时火焰图)
JS 特性主线(全 15 章打满):
- Symbol / 迭代器:
Symbol做唯一 effect ID、Symbol.iterator让数据集可枚举、Symbol.toPrimitive自定义图例显示 - 原型链 / 面向对象:
Plugin基类继承、extends EventEmitter、私有字段#state、Reflect元编程 - 标准库:
WeakMap存 effect 依赖(讲清为什么不用 Map:内存泄漏!)、WeakSet、Set、Map、Date/Intl - 异步:WebSocket + 心跳 / 重连指数退避、
requestAnimationFrame调度渲染、WorkerpostMessage协议、批量更新调度(micro task 合并) - 事件:自实现
EventEmitter(on/off/once/emit),new EventTarget()原生方案对比 - 错误:异步 Error Boundary、Sentry 风格错误上报封装、
window.onerror/unhandledrejection双兜底 - DOM:
MutationObserver监听容器尺寸变化、ResizeObserver响应式尺寸、Canvas 高清屏 dpr 缩放 - 网络:
fetch流式 + WebSocket + IndexedDB Promise 化封装 - 模块化:ESM + 动态
import()+ tree-shaking 友好导出 + UMD 打包脚本(esbuild) - 字符串:模板引擎手写(
替换 + 简单 AST + 表达式求值)
架构亮点:
┌─ Reactivity(Proxy + Dep) ── 响应核心(mini-vue)
├─ Renderer(Canvas) ── 视图层(复用案例 03 高频渲染)
├─ Pipeline(异步数据流) ── 数据层(复用案例 02)
├─ EventBus(自实现) ── 解耦
├─ Plugin(生命周期钩子) ── 扩展
└─ Devtools(性能 + 状态) ── 可观测
2
3
4
5
6
对应章节反查表(毕业设计专用):
| JS 章节 | 在 jschart 的落地点 |
|---|---|
| 01 入门 / 语法 | 整个项目 |
| 02 数据类型 | WeakMap 依赖图、Set 副作用集合 |
| 03 运算符 | 可选链 / 空值合并 / 位运算压缩配置 |
| 04 函数 | 闭包封装 effect、柯里化高阶组件 |
| 05 面向对象 | Plugin 继承、原型链方法查找 |
| 06 标准库 | Map / Set / Date / Math / JSON / Intl |
| 07 异步操作 | rAF 调度、WebSocket、Worker |
| 08 事件设计 | EventEmitter / EventTarget 双实现 |
| 09 错误机制 | Error Boundary + 上报 |
| 10 模块开发 | ESM / 动态 import / UMD 三套 |
| 11 字符串 | 模板引擎手写 |
| 12 迭代器 | 数据集 Symbol.iterator |
| 13 Symbol | effect 唯一 ID、私有协议字段 |
| 14 DOM | Canvas + MutationObserver + dpr |
| 15 网络 | fetch + WS + IndexedDB |
反模式对照(最后一章集中讲 8-10 条工程反模式):
- ❌ 用
Object.defineProperty实现响应式(无法监听新增属性)→ ✅Proxy全代理 - ❌ Effect 依赖用
Map(永远不释放)→ ✅WeakMap+WeakSet - ❌ 数据每变一次重渲一次 → ✅ 微任务批量合并(
queueMicrotask) - ❌ Canvas 直接按 CSS 像素画(高清屏模糊)→ ✅
dpr缩放 - ❌ Worker 用
JSON.stringify传大数据 → ✅TransferableArrayBuffer零拷贝
产出物:~3500 行 JS + 完整 Vite 工程;可发布为 npm 包;附带 Devtools Chrome Extension 雏形。
# 05.案例间承接关系(业务 + 技术双线)
01 jstodo(浏览器交互入门:DOM + 事件 + 模块)
│
│ 痛点:"数据要从服务器拉?" → 异步与网络
│ 痛点:"请求并发怎么管?" → Promise / 生成器
▼
02 jsfeed(异步流水线:Promise + 流式 + 生成器)
│
│ 痛点:"文本数据玩腻了,能播视频吗?" → 二进制流 / MSE
│ 痛点:"如何驯服浏览器原生组件?" → Web 平台 API
▼
03 jsplayer(H5 视频播放器:Web API 大全 + Canvas 渲染)
│
│ 痛点:"数据变了怎么自动刷新视图?" → 响应式
│ 痛点:"想把所有能力合一做产品?" → 毕业设计
▼
04 jschart(响应式 + Canvas + 全 15 章串联)🎓
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
与 C++ / Go 综合案例的对仗设计:
| 卷 | 灵魂特性 | 入门案例 | 毕业设计 |
|---|---|---|---|
| C++ 17 章 | OOP + 内存模型 | 学生通讯录 | MiniKVStore(KV 存储引擎) |
| Go 18 章 | 并发 + 工程化 | gotodo(CLI) | gosite(静态博客生成器) |
| JS 15 章 | Web 平台 API + 响应式 | jstodo(DOM/事件) | jschart(响应式数据看板) |
三门语言的综合案例毕业设计分别对应 "系统级 / 工程级 / Web 级" 三种典型形态。
# 06.推荐学习路径
# 路径 A:新手线(按顺序通读,强烈推荐)
01 jstodo(DOM/事件入门,5 h)
↓ 升级为异步 + 网络
02 jsfeed(异步流水线大考,10 h)
↓ 加 Web 平台 API + 二进制流
03 jsplayer(H5 视频播放器,12 h)
↓ 集大成
04 jschart(毕业设计:复用前 3 个产物,串完卷一所有 15 章,16 h)
2
3
4
5
6
7
总耗时约 43 小时,相当于:每天 2 小时 × 22 天 / 周末全天 × 5 周。
# 路径 B:带 Java/Python 转 JS(按主题跳读)
DOM / 事件 主题: 01 → 03(视频控件) → 04(看板交互)
异步主题: 02(异步全家桶) → 04(响应式调度)
浏览器 API 主题: 03(视频/Canvas/PiP/MSE) → 04(Worker/IndexedDB/WebSocket)
工程化主题: 01(ESM 起步) → 04(Vite + 插件 + UMD)
2
3
4
# 路径 C:快速查漏(按卷一章节反查)
| 想练习的卷一章节 | 优先看哪个案例 |
|---|---|
| 第 02 章 数据类型(Map/WeakMap/Set) | 全部,重点 04 jschart |
| 第 04 章 函数(闭包/高阶) | 全部,重点 02(pLimit)/ 04(effect) |
| 第 05 章 面向对象(class/继承/私有字段) | 03 jsplayer(继承 EventTarget)/ 04 |
| 第 07 章 异步操作(Promise/async) | 02 jsfeed(异步全家桶)/ 04 |
| 第 08 章 事件设计(委托/冒泡) | 01 jstodo(事件委托)/ 03 / 04 |
| 第 09 章 错误机制 | 02 jsfeed(自定义 Error 体系)/ 04 |
| 第 10 章 模块开发(ESM) | 全部,重点 02 / 04 |
| 第 11 章 字符串(模板/正则) | 04 jschart(手写模板引擎) |
| 第 12 章 迭代器与生成器 | 02 jsfeed(async function* 分页) |
| 第 13 章 Symbol | 04 jschart(effect 唯一 ID) |
| 第 14 章 DOM 操作 | 01 jstodo(事件委托 + diff)/ 03 jsplayer(Canvas) |
| 第 15 章 网络请求(fetch/WS) | 02 jsfeed(fetch 封装)/ 03 jsplayer(Range/MSE)/ 04(WS) |
| 想一次性串完卷一所有章节 | 直接做 04 jschart |
# 07.统一的写作约定
为保证 4 个案例 "看起来像一本书",本卷遵循以下统一约定:
# 7.1 每篇八段式结构
| 段 | 内容 | 字数 |
|---|---|---|
| 1. 需求拆解 | 真实场景 + 功能清单 + 不做什么 | 1500 |
| 2. 架构设计 | mermaid 模块图 + 数据流图 + 关键决策 | 2000 |
| 3. 核心数据结构 | 核心 class / 类型定义与权衡 | 2000 |
| 4. 关键流程逐段实现 | 按"功能切片"展示完整可跑代码 | 8000 |
| 5. 反模式对照 | 5-8 条 ❌ vs ✅ | 2500 |
| 6. 测试与基准 | 浏览器 console 测试 / performance.now() benchmark | 1500 |
| 7. 卷一章节反向索引 | 表格:本案例第 X 节 ↔ 卷一第 Y 章 | 500 |
| 8. 拓展挑战 | 3-5 个进阶练习题(思考、不给答案) | 500 |
| 合计 | — | ~1.8 万字 |
# 7.2 代码风格
| 项目 | 约定 |
|---|---|
| 命名 | 类 PascalCase、函数/变量 camelCase、常量 UPPER_SNAKE、私有字段 #prefix |
| 模块 | 默认 ESM;文件后缀 .js(教学清晰);避免 default export,统一 named export |
| 字符串 | 一律单引号 ';插值用模板字符串 ` |
| 分号 | 行尾加分号(避免 ASI 陷阱) |
var 使用 | 禁止,一律 const 优先、let 次之 |
== 使用 | 禁止,一律 === / !== |
| 异步 | async/await 优先;底层抽象(如 pLimit)允许 Promise.then |
| 错误 | 自定义 Error 必须 extends Error 并设 this.name |
| 标准 | 基线 ES2022;用到 ES2023+ 特性会标注 🆕 ES2023 |
| 测试 | 浏览器 console + performance.now();不引入 Jest / Vitest(保持零依赖) |
# 7.3 术语统一
| 术语 | 本卷统一译法 |
|---|---|
| Promise | Promise(不译) |
| async/await | async / await(不译) |
| event loop | 事件循环 |
| event delegation | 事件委托 |
| reactive | 响应式 |
| reactivity | 响应式系统 |
| signal | 信号(Solid 风格 reactive 单元) |
| observer | 观察者 |
| effect | 副作用 / effect |
| host environment | 宿主环境 |
| Web Platform API | Web 平台 API |
# 08.常见疑问 FAQ
Q1:为什么是 4 个案例,不是 3 个或 5 个?
A:复盘前期 "3 案例方案"(jstodo / jsfeed / jschart),发现一个硬伤——Web 平台 API 没有专门的承载案例。Web API 是 JS 区别于 C++/Go 的灵魂(MSE / Fullscreen / PiP / Canvas / WebVTT...),如果只在 jschart 里 "顺带提一下",会让读者错过 "前端工程师 80% 工作是驯服浏览器" 的真相。因此插入 03 jsplayer 专门承载这块——视频播放器是一次性集中演练 10+ 个宿主 API 的最佳载体。
Q2:为什么不引入 Vue / React / Axios / Lodash?
A:本卷的目标是 让读者亲眼看到框架的轮子是怎么造的——
- 04
jschart手写响应式 → 看到 Vue 的 Proxy 是怎么工作的 - 02
jsfeed手写 fetch 拦截器和 pLimit → 看到 Axios 的设计来源 - 03
jsplayer手写迷你 HLS → 看到 video.js / hls.js 的核心思路
如果一开始就 npm install vue,读者会陷入 "用 API 而不懂原理" 的舒适陷阱。等本卷四个案例做完,再去学 Vue / React 会有 "原来如此" 的爽感。
Q3:03 jsplayer 真的需要吗?看起来跟 02 / 04 不那么相关?
A:相关性体现在三个层面——
- 技术依赖:03 复用 02 的
AbortController/fetch流式;04 复用 03 的 Canvas 高频渲染 + RAF 调度 - 认知阶梯:02 解决 "异步" 的认知断层,03 解决 "宿主 API" 的认知断层,04 解决 "响应式" 的认知断层;缺一个都会让 04 毕业设计的某些章节显得突兀
- 就业价值:前端面试高频题 "实现一个视频播放器 / 弹幕系统" 几乎必考,03 直接对标真实工作场景
Q4:4 个案例之间能跳着学吗?
A:前 3 个建议按顺序学,因为存在严格的技术依赖(02 的 AbortController → 03 的码率切换;03 的 Canvas → 04 的图表引擎)。第 4 个毕业设计可以等前 3 个学完后再做,体感会有 "原来如此" 的爽感。
Q5:完成 4 个案例后我的水平能到哪?
A:参考下方 "学习效果检验标准"——具备 独立开发现代浏览器应用 的能力,可以阅读 Vue 3 / React / hls.js / ECharts 的核心源码,能够无缝进入 Vue / React 框架学习,或独立承担一个中型前端项目。
Q6:4 个案例总共多少代码?多久能走完?
A:合计约 8000 行 JS 代码(不含 HTML/CSS),约 8 万字讲解。按每周 1 个案例的节奏,4 周可以走完全部。如果只想快速验收卷一,做 01 + 02 + 04 三个就够了(约 3 周);如果想把 Web 平台 API 一次性吃透,强烈建议加做 03。
# 09.学习效果检验标准
完成本卷 4 个案例后,你应该能够:
✅ 基础能力
- 熟练使用 ES2022+ 核心特性(Proxy / 私有字段 / 顶层 await / 可选链 / 空值合并 / async iterator)
- 理解 JS 异步模型(事件循环 / 宏任务 / 微任务 / Promise 状态机)
- 掌握原型链 / 闭包 /
this绑定三大经典难点
✅ 工程能力
- 设计可维护的 ESM 多模块前端项目(state / view / store / network / plugin 分层)
- 处理浏览器宿主 API(DOM / Canvas / fetch / WebSocket / Worker / IndexedDB / Media)
- 排查内存泄漏(监听器未卸载 / 闭包持有 / Map 持久引用)
- 优化性能(事件委托 / RAF 调度 / 微任务批量合并 / Worker 卸载)
✅ 系统思维
- 从需求分析到代码实现的全流程能力
- 能手写迷你版 Vue / Axios / hls.js 核心,理解框架来源
- 错误处理设计能力(自定义 Error 继承 / 错误边界 / 全局兜底)
✅ 进阶准备
- 为学习 Vue / React / Node.js 打下坚实基础
- 具备阅读开源 JS 项目(Vue 3 / hls.js / ECharts / koa)的能力
- 能够独立开发中型前端应用,无缝进入框架卷 / 工程卷
# 10.与其他卷的衔接
| 案例 | 反向衔接卷一《基础入门》 | 正向衔接卷三《专栏博客》 |
|---|---|---|
| 01 jstodo | 第 02-06、08-10、14 章 | 卷三 "DOM 渲染机制 / 事件循环原理" |
| 02 jsfeed | 第 07、09、12、13、15 章 | 卷三 "Promise 内部实现 / 异步迭代器原理" |
| 03 jsplayer | 第 05、06、08、14、15 章 | 卷三 "渲染流水线 / 合成层 / 媒体管线" |
| 04 jschart | 全 15 章 | 卷三 "Proxy 元编程 / V8 隐藏类 / GC 与 WeakRef" |
具体阅读顺序建议:
- 卷一《基础入门》:本卷是它的验收考。做不动的话回头复习对应章节。
- 卷三《专栏博客》:本卷的 "原理" 部分只做到 "够用";想看 V8 引擎、JIT 编译、GC、隐藏类,去卷三专栏深挖。
- 框架卷(Vue / React):完成本卷 04 jschart 后再去学 Vue / React 会有 "原来响应式 / 虚拟 DOM 是这么回事" 的爽感。
# 11.卷首寄语
"JavaScript is the only language that I'm aware of that people feel they don't need to learn before they start using it." — Douglas Crockford
卷一教会你怎么写每一行 JS 代码;卷二要教会你怎么把一千行 JS 代码组织成一个能跑、能改、能上线的浏览器产品。
4 个案例,从一个 800 行的待办清单,到一个 3500 行的响应式数据看板——你会经历每一个前端工程师都经历过的 "啊,原来这样写" 的瞬间:
- 第一次发现 "原来事件委托能省 N 次绑定" —— 案例 01
- 第一次发现 "原来
forEach里await是无效的" —— 案例 02 - 第一次发现 "原来
<video>有 24 个事件,timeupdate卡顿要换requestVideoFrameCallback" —— 案例 03 - 第一次发现 "原来 Vue 的响应式核心只要 100 行 Proxy" —— 案例 04
翻开第 1 章,让我们从 jstodo 开始。
➡ 下一章:案例 01 · 待办清单事件驱动