跳转到内容

JavaScript纯函数

来自代码酷
Admin留言 | 贡献2025年4月30日 (三) 19:06的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)

JavaScript纯函数

纯函数(Pure Function)是函数式编程中的核心概念之一,它指的是在相同的输入下始终返回相同的输出,并且不会产生任何副作用(Side Effects)的函数。纯函数的设计使得代码更易于测试、调试和维护,同时提高了程序的可预测性。

定义与特性

纯函数必须满足以下两个条件:

  1. 确定性:给定相同的输入,总是返回相同的输出。
  2. 无副作用:不会修改任何外部状态(如全局变量、传入的参数等),也不会产生可观察的副作用(如网络请求、DOM操作等)。

数学上,纯函数可以表示为: f(x)=y 其中,函数 f 对于相同的 x 总是返回相同的 y

示例:纯函数与非纯函数

// 纯函数示例
function add(a, b) {
    return a + b;
}

console.log(add(2, 3)); // 输出:5(始终相同)

// 非纯函数示例(依赖外部变量)
let counter = 0;
function increment() {
    counter++; // 修改外部状态
    return counter;
}

console.log(increment()); // 输出:1(但下次调用可能不同)

为什么使用纯函数?

纯函数具有以下优势:

  • 可预测性:相同的输入总是产生相同的输出。
  • 可测试性:无需依赖外部状态,测试更简单。
  • 可缓存性(Memoization):可以缓存函数结果以提高性能。
  • 并行安全:纯函数不会因并发执行而产生竞态条件(Race Condition)。

实际应用案例

1. 数据处理与转换

纯函数常用于数据转换,例如数组操作:

const numbers = [1, 2, 3, 4];

// 纯函数:map 不会修改原数组
const doubled = numbers.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8]

2. Redux 中的 Reducer

在 Redux 中,Reducer 必须是纯函数:

function counterReducer(state = 0, action) {
    switch (action.type) {
        case 'INCREMENT':
            return state + 1; // 返回新状态,而非修改原状态
        default:
            return state;
    }
}

如何编写纯函数

1. 避免修改参数:直接修改传入的对象或数组会使其成为非纯函数。 2. 避免依赖全局状态:使用参数传递所需数据。 3. 隔离副作用:将副作用(如API调用)与纯逻辑分离。

示例:避免参数修改

// 非纯函数(修改参数)
function updateUserImpure(user) {
    user.age = 30; // 直接修改参数
    return user;
}

// 纯函数(返回新对象)
function updateUserPure(user) {
    return { ...user, age: 30 }; // 使用展开运算符创建新对象
}

纯函数的局限性

纯函数无法处理以下场景:

  • 需要与外部系统交互(如数据库、API调用)。
  • 需要修改DOM或浏览器状态。
  • 需要随机数生成(如 `Math.random()`)。

总结

纯函数是函数式编程的基石,它通过避免副作用和确保确定性来提升代码质量。尽管并非所有函数都能是纯函数,但在可能的情况下优先使用纯函数可以显著提高代码的可维护性和可靠性。

对比图表

pie title 纯函数 vs 非纯函数 "确定性" : 40 "无副作用" : 40 "可测试性" : 20

练习

尝试将以下非纯函数改写为纯函数:

let total = 0;
function addToTotal(value) {
    total += value;
    return total;
}