JavaScript高级程序设计笔记 28
第 28 章 最佳实践
学习目标:从可维护性、性能和部署三个角度理解 JavaScript 项目工程实践,形成可长期维护、可优化、可上线的代码意识。
1. 本章核心脉络
JavaScript 不只是语法和 API。真实项目还要考虑代码是否容易维护、运行是否高效、上线过程是否可靠。本章把重点放在工程实践上:
- 可维护性:代码清晰、规范、低耦合、容易修改。
- 性能:减少不必要的计算、访问和 DOM 操作。
- 部署:构建、验证、压缩和发布。
2. 可维护性
2.1 什么是可维护的代码
可维护代码通常具备:
- 容易理解。
- 命名清晰。
- 结构一致。
- 职责单一。
- 注释恰当。
- 低耦合。
- 修改局部代码不容易影响全局。
判断标准不是“代码看起来高级”,而是团队成员在几个月后仍能快速理解并安全修改。
2.2 编码规范
编码规范让团队代码保持一致。
常见规范内容:
- 缩进。
- 变量命名。
- 文件命名。
- 注释风格。
- 函数长度。
- 模块组织。
- 错误处理方式。
- 类型和接口约定。
现代项目一般通过工具固化规范:
- ESLint:代码质量检查。
- Prettier:格式化。
- TypeScript:类型约束。
- EditorConfig:编辑器基础风格。
2.3 命名
命名要表达意图。
不推荐:
const d = new Date();
const arr = users.filter((x) => x.a);
更清晰:
const currentDate = new Date();
const activeUsers = users.filter((user) => user.isActive);
实践建议:
- 布尔值使用
is、has、can、should。 - 函数名使用动词或动宾结构。
- 集合使用复数。
- 避免无意义缩写。
2.4 注释
注释应该解释“为什么”,而不是重复“做了什么”。
好注释适合:
- 解释复杂业务规则。
- 说明兼容性处理原因。
- 标注权衡和限制。
- 记录非直觉实现的背景。
不好的注释:
// i 加 1
i++;
更有价值的注释:
// 服务端分页从 1 开始,组件内部页码从 0 开始。
const requestPage = currentPage + 1;
2.5 松散耦合
低耦合意味着模块之间依赖少、边界清晰。
常见方向:
- JavaScript 与 HTML 解耦。
- CSS 与 JavaScript 解耦。
- 应用逻辑与事件处理解耦。
- 数据层与视图层解耦。
- 业务规则与工具函数解耦。
不推荐把行为写进 HTML:
<button onclick="save()">保存</button>
更推荐:
document.querySelector("#save").addEventListener("click", save);
2.6 编码惯例
实践建议:
- 不修改不属于自己的对象,尤其是原生对象原型。
- 避免全局变量。
- 每个函数只做一件事。
- 常量集中管理。
- 对外暴露稳定接口。
- 对错误路径有明确处理。
- 删除无用代码,而不是长期注释。
3. 性能
3.1 性能优化原则
性能优化应基于测量,而不是猜测。
基本流程:
- 发现性能问题。
- 使用工具定位瓶颈。
- 做小范围优化。
- 再次测量验证结果。
常用工具:
- Chrome DevTools Performance。
- Lighthouse。
- Network 面板。
- Coverage。
- Memory 面板。
3.2 作用域意识
变量查找会沿作用域链向外查找。现代引擎已经很强,但仍应保持代码结构清晰,避免不必要的全局访问和深层闭包滥用。
实践建议:
- 局部变量缓存重复使用的值。
- 避免在热路径中访问复杂链式属性。
- 避免不必要的闭包保留大对象。
const { length } = items;
for (let i = 0; i < length; i++) {
// ...
}
3.3 选择正确的方法
不同写法的性能和语义都可能不同。应先保证语义清晰,再关注性能。
常见建议:
- 高频路径中避免重复创建对象和函数。
- 大量字符串拼接可考虑数组或模板生成策略。
- 需要快速查找时,用
Map或Set替代数组线性搜索。 - 大数据列表渲染使用分页或虚拟列表。
- 防抖和节流处理高频事件。
示例:
const selectedIds = new Set(ids);
const selectedUsers = users.filter((user) => selectedIds.has(user.id));
3.4 语句最少化
减少不必要语句可以降低执行成本,也能提升可读性。
常见手段:
- 合并重复逻辑。
- 避免重复条件判断。
- 提前返回减少嵌套。
- 把复杂逻辑拆成清晰函数。
function getDiscount(user) {
if (!user.isMember) {
return 0;
}
if (user.level === "vip") {
return 0.2;
}
return 0.1;
}
3.5 优化 DOM 交互
DOM 操作通常比纯 JavaScript 计算更昂贵,尤其是频繁读写布局信息时。
实践建议:
- 批量 DOM 更新。
- 使用
DocumentFragment或一次性字符串渲染。 - 避免在循环中反复触发布局。
- 缓存 DOM 查询结果。
- 使用事件委托。
- 对长列表使用虚拟滚动。
- 用 CSS class 切换样式,而不是逐项修改内联样式。
事件委托:
list.addEventListener("click", (event) => {
const button = event.target.closest("button[data-id]");
if (!button) {
return;
}
handleClick(button.dataset.id);
});
避免布局抖动:
const width = element.offsetWidth;
items.forEach((item) => {
item.style.width = `${width}px`;
});
不要在循环中交替读取布局和写入样式。
4. 部署
4.1 构建流程
现代前端部署通常会经历:
- 安装依赖。
- 静态检查。
- 单元测试。
- 构建打包。
- 资源压缩。
- 文件指纹。
- 上传 CDN 或服务器。
- 发布验证。
常见构建工具:
- Vite。
- Webpack。
- Rollup。
- esbuild。
- SWC。
4.2 验证
上线前应尽可能自动验证:
- 语法检查。
- 类型检查。
- 单元测试。
- 集成测试。
- 构建是否成功。
- 关键页面 smoke test。
- bundle 体积检查。
示例 npm scripts:
{
"scripts": {
"lint": "eslint src",
"typecheck": "tsc --noEmit",
"test": "vitest",
"build": "vite build"
}
}
4.3 压缩
压缩可以减少网络传输体积。
常见处理:
- 删除空白和注释。
- 缩短局部变量名。
- 移除不可达代码。
- 合并和优化表达式。
- Tree shaking。
- gzip 或 Brotli 传输压缩。
注意:
- 压缩代码要保留 source map,方便线上排错。
- source map 是否公开要根据安全策略决定。
- 文件名加内容 hash,便于长期缓存。
4.4 缓存与发布
静态资源常用策略:
- JS/CSS 文件名带 hash,设置长期缓存。
- HTML 不做强长期缓存,确保能拿到新资源入口。
- CDN 刷新和回滚流程要清晰。
- 重要发布要有监控和错误告警。
5. 工程实践建议
5.1 可维护性优先级
优先保证:
- 代码能被团队理解。
- 变更影响范围可控。
- 错误能被发现。
- 构建和发布可重复。
不要为了微小性能收益牺牲明显可读性,除非测量证明这是瓶颈。
5.2 性能优化优先级
通常优先关注:
- 网络请求数量和体积。
- 首屏渲染资源。
- 大量 DOM 更新。
- 长任务。
- 内存泄漏。
- 重复渲染。
5.3 部署可靠性优先级
上线链路应做到:
- 可自动化。
- 可验证。
- 可回滚。
- 可观测。
6. 面试高频问题
6.1 什么是可维护代码?
可维护代码是容易理解、容易修改、容易测试、行为可预测的代码。它通常命名清晰、职责单一、耦合低,并遵循统一规范。
6.2 如何减少 JavaScript 与 HTML 的耦合?
避免内联事件处理,把行为绑定放在 JavaScript 中,通过选择器、事件监听和组件接口建立关系。
6.3 前端性能优化从哪里入手?
先测量,再优化。通常从网络体积、首屏渲染、长任务、DOM 操作、重复计算和内存泄漏入手。
6.4 为什么 DOM 操作昂贵?
DOM 操作可能触发布局计算、样式重算和绘制。频繁读写布局信息还可能造成布局抖动,影响页面流畅度。
6.5 什么是 Tree shaking?
Tree shaking 是构建工具基于静态依赖分析移除未使用代码的优化。ES Module 的静态导入导出让它更容易实现。
6.6 为什么静态资源文件名要带 hash?
文件内容变化时 hash 变化,浏览器会请求新文件;内容不变时可以长期缓存。这能兼顾缓存效率和更新正确性。
7. 复习清单
8. 一句话总结
第 28 章的核心是把 JavaScript 写成可长期演进的软件:用规范和低耦合保证可维护性,用测量驱动性能优化,用自动化构建和验证保证部署可靠性。

浙公网安备 33010602011771号