纯函数是函数式编程的基石,必须同时满足确定性(输入相同则输出相同)和无副作用(不读写外部状态、不修改参数),其价值在于简化测试、安全组合、便于缓存与调试;副作用需隔离封装而非消灭。

纯函数是函数式编程的基石,不是风格偏好,而是可预测性与可控性的硬性要求。它用两条铁律定义:输入相同,输出必相同;不读不写外部状态,不改变参数本身。
纯函数的两个必要条件
一个函数要被认定为纯函数,必须同时满足:
-
确定性:比如
Math.abs(-5)每次都返回5,String.prototype.toUpperCase.call('hi')总是得'HI';但Date.now()、Math.random()、localStorage.getItem('x')违反这条,因为结果随环境漂移 -
无副作用:不能修改传入的对象或数组(如
arr.push()、obj.name = 'a')、不能调用console.log或alert、不能发起请求、不能更改 DOM 或全局变量
常见“伪纯函数”陷阱
表面简洁,实则暗藏杂质,这些写法极易误判:
- 用
Array.prototype.sort()—— 它直接修改原数组,应改用[...arr].sort() - 对对象参数做赋值:
user.age = 30破坏纯度,正确做法是返回新对象:{ ...user, age: 30 }或用structuredClone(user) - 隐式依赖外部变量:
const baseUrl = 'https://api.example.com'; const fetchUser = id => fetch(`${baseUrl}/users/${id}`)—— 把baseUrl作为参数显式传入才符合纯度
为什么坚持纯函数值得
它带来的不是理论优势,而是日常开发中可感知的收益:
立即学习“Java免费学习笔记(深入)”;
-
测试极简:给定
add(2, 3),预期就是5,无需 mock 时间、网络或全局状态 -
安全组合:多个纯函数可自由拼接,例如
compose(formatPhone, toUpperCase, trim),每一步都稳如磐石 - 便于缓存与重放:只要输入没变,结果就可复用(如 React.memo 或自定义记忆化 memoize)
- 利于调试与追踪:数据流单向、透明,出错时只需检查输入和函数逻辑,不用翻全局状态
副作用不是敌人,而是需要安置的位置
真实应用离不开副作用,关键在于隔离而非消灭:
- 把副作用封装成独立函数,如
loadUserData()、saveSettings(data) - 在纯函数中只做数据转换,让副作用发生在明确可控的边界(如组件的 useEffect、Redux 的 Thunk)
- 用命名提示行为性质,例如
fetchUserAsync()、updateUIInPlace(),让调用者一眼识别风险区



















