纯函数是输入相同则输出恒定、无副作用的函数,它通过参数显式传递不确定性(如时间、随机数、API响应)、用高阶函数封装副作用、配合不可变更新,实现逻辑可测、可复用、状态可预测。

用纯函数优化 JavaScript 代码,核心是让函数行为确定、边界清晰、依赖可控——这直接降低测试成本,提升逻辑复用效率。
纯函数是什么,为什么它天然可测
纯函数满足两个硬性条件:相同输入永远返回相同输出;不修改外部变量、不读写 localStorage、不调用 Date.now() 或 fetch() 等产生不确定结果的操作。比如:
-
✅ 纯函数:
const sum = (a, b) => a + b;—— 输入 2 和 3,永远得 5 -
❌ 非纯函数:
let count = 0; const inc = () => ++count;—— 每次调用结果不同,还污染了外部状态
正因为输出只取决于输入,单元测试时只需准备几组输入/预期输出,无需 mock 全局时间、网络或 DOM,断言也简洁明确。
把“不稳定因素”变成参数,让函数回归纯粹
现实业务中,时间、随机数、API 调用等无法避免。关键不是不用它们,而是把它们从函数内部“抽出来”,作为显式参数传入:
立即学习“Java免费学习笔记(深入)”;
- 把
formatDate(new Date())改成formatDate(date),测试时传new Date('2023-01-01') - 把
Math.random()封装为getRandom(seed),测试时传固定 seed - 把直接调用的
localStorage.getItem('theme')提取为参数getTheme(),测试时传一个返回 'dark' 的函数
这样既保留了业务灵活性,又让主逻辑彻底脱离环境依赖,测试时可完全控制输入流。
用高阶函数封装副作用,保持业务层干净
纯函数不等于不能处理副作用,而是要把副作用“集中收口”。高阶函数是理想的胶水:
- 写一个
withLoading高阶函数,接收原始业务函数,自动包装 loading 状态和错误处理 - 用
retry(fetchUser, { max: 3 })包裹请求逻辑,重试策略与用户获取逻辑解耦 - 在 React 中,自定义 Hook 如
useApi统一管理请求副作用,组件内只调用纯的 data transform 函数
业务函数专注“数据怎么变”,不关心“什么时候变”或“失败怎么办”,复用场景大幅拓宽——同一套转换逻辑,既可用于 API 响应,也可用于本地缓存或 Mock 数据。
配合不可变更新,让状态变更可预测、可回溯
纯函数常与不可变数据操作搭配使用。避免 obj.name = 'x' 这类就地修改,改用展开运算符或结构化赋值:
const newUser = { ...user, name: 'Alice' };const updatedList = list.map(item => ({ ...item, active: true }));
这样不仅避免意外修改原始数据,还能天然支持时间旅行调试(如 Redux DevTools)、状态快照比对、以及基于引用的渲染优化(React.memo)。


















