纯函数要求相同输入恒得相同输出,且无状态依赖与副作用;需满足确定性、无状态依赖、无副作用三标准,副作用应显式封装而非消除。

纯函数是函数式编程的核心,它要求相同的输入永远返回相同的输出,且不修改外部状态、不依赖外部变量、不产生副作用。控制副作用的关键,在于把“变化”显式化、隔离化、可追踪化——不是消灭副作用,而是让它们不再偷偷发生。
纯函数的三个判断标准
一个函数要成为纯函数,必须同时满足:
-
确定性:给定相同参数,结果恒定不变(比如
Math.max(2, 3)每次都返回5) -
无状态依赖:不读取或修改闭包外的变量、全局变量、对象属性等(避免
let count = 0; const inc = () => ++count;这类行为) -
无副作用:不发起网络请求、不修改 DOM、不写入 localStorage、不调用
console.log或alert
副作用不是“坏东西”,而是需要被管理的东西
真实应用离不开副作用(如获取用户数据、保存设置、渲染界面),函数式编程的思路不是禁用它们,而是:
- 把副作用操作单独封装成函数(如
fetchUser(id)、saveToStorage(data)) - 在纯函数中只做数据转换,把副作用推迟到明确可控的位置(例如 React 的
useEffect、Redux 的 middleware) - 用类型或命名提示副作用(如函数名加
Async、Mutate后缀,或用IO类型包裹)
常见“看似纯、实则不纯”的陷阱
这些写法容易误判为纯函数,但实际存在隐式依赖或变更:
-
修改传入的对象/数组:
const addProp = obj => { obj.newField = true; return obj; }—— 应改用展开语法或Object.assign({}, obj, {...}) - 依赖 Date.now() 或 Math.random() —— 它们每次调用结果不同,破坏确定性;可改为接收时间戳或随机数作为参数
-
读取全局配置或环境变量(如
process.env.NODE_ENV)—— 若逻辑随环境变化,就不是纯函数;应将配置显式传入
用组合与柯里化支撑纯函数体系
纯函数天然适合组合。例如:
const formatName = compose(toUpperCase, trim, getFullName);
柯里化能帮助固定部分参数、延迟执行、提升复用性:
const filterBy = key => value => item => item[key] === value;-
const isActive = filterBy('status')('active');—— 得到一个纯的、可复用的过滤器
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











