
## 1. 核心概念 (Core Concept)

*   **纯函数 (Pure Function)**：指满足两个条件的函数：给定相同的输入，总是返回相同的输出；并且执行过程中没有任何可观察的副作用。
*   **副作用 (Side Effect)**：指函数执行时，除了返回显而易见的计算结果外，还对外部世界产生了可观察的影响，例如修改全局变量、I/O 操作（读写文件、网络请求）、修改 DOM 等。
*   **函数式编程 (Functional Programming)**：一种编程范式，强调使用纯函数、避免改变状态和可变数据，并使用函数作为一等公民。它将计算视为数学函数的求值。

## 2. 为什么需要它？ (The "Why")

*   **可预测性与可测试性 (Predictability & Testability):** 纯函数由于其确定的输入和输出，极大地提高了代码的可预测性，使得单元测试变得非常简单，只需测试输入与输出的关系即可。
*   **并发与并行安全性 (Concurrency & Parallel Safety):** 纯函数不依赖或修改外部状态，天然适用于并发和并行环境，避免了多线程或多进程共享状态带来的复杂同步问题（如竞态条件）。
*   **代码理解与推理 (Code Understanding & Reasoning):** 副作用使得代码的行为难以追踪，因为它的行为取决于外部状态。纯函数将复杂性局部化到函数内部，使得代码更容易理解和推导其行为。

## 3. API 与用法 (API & Usage)

纯函数本身不是一个具体的 API，而是函数的一种属性或一种编写函数的方式。函数式编程也没有特定的内置 API（在通用编程语言如 JavaScript 中），它更多是一种编程风格和思想。

纯函数的例子（JavaScript）：

```javascript
// 纯函数：给定相同的输入 (a, b)，总是返回相同的输出 (a + b)，没有副作用。
function add(a, b) {
  return a + b;
}

// 非纯函数的例子 (含有副作用)：
// 例子 1: 依赖外部状态
let count = 0;
function incrementAndGet() {
  count++; // 修改外部变量，副作用
  return count;
}

// 例子 2: 修改传入的参数 (如果参数是引用类型)
function modifyArray(arr) {
  arr.push(1); // 修改了函数外部的数组，副作用
  return arr;
}

// 例子 3: 进行 I/O 操作
function logMessage(message) {
  console.log(message); // 写入到控制台，副作用 (尽管这是常见的操作)
}

// 例子 4: 读取外部状态
function getRandomNumber() {
  return Math.random(); // 依赖 Math 的内部状态（或者说依赖时间等外部因素），每次结果不同，非纯函数
}
```

在函数式编程中，我们通常会结合使用高阶函数（Higher-Order Functions，如 `map`, `filter`, `reduce`）和纯函数来处理数据：

```javascript
// 使用纯函数和高阶函数处理数组
const numbers = [1, 2, 3, 4, 5];

// 使用 map (高阶函数)，传入一个纯函数 (num => num * 2)
// map 本身是纯的，它返回一个新数组，不修改原数组
const doubledNumbers = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]

// 使用 filter (高阶函数)，传入一个纯函数 (num => num > 2)
// filter 本身是纯的，它返回一个新数组
const greaterThanTwo = numbers.filter(num => num > 2); // [3, 4, 5]

// 使用 reduce (高阶函数)，传入一个纯函数 ((acc, num) => acc + num)
// reduce 本身是纯的，它返回一个单一值
const sum = numbers.reduce((acc, num) => acc + num, 0); // 15

console.log("Original:", numbers); // [1, 2, 3, 4, 5] - 原数组未被修改
console.log("Doubled:", doubledNumbers);
console.log("Filtered:", greaterThanTwo);
console.log("Sum:", sum);
```

## 4. 关键注意事项 (Key Considerations)

*   **并非所有函数都能是纯函数:** 在实际应用中，完全没有副作用的程序是不可能的（比如最终需要将结果显示给用户，这就需要 I/O 副作用）。关键在于**控制副作用，将其隔离在程序的边缘**。
*   **修改引用类型参数的陷阱:** JavaScript 中，Objects 和 Arrays 是通过引用传递的。如果函数修改了作为参数传入的引用类型对象或数组，就产生了副作用。为了保持纯净，应返回新的对象或数组，而不是修改原有的。可以使用展开运算符 `...`、`slice()`、`map()`、`filter()` 等方法创建副本。
*   **理解状态管理的边界:** 在前端框架（如 React、Vue）中处理状态时，理解何时需要管理具有副作用的状态（如组件状态、全局状态）以及何时使用纯函数进行计算，是构建可维护应用的关键。许多现代状态管理库（如 Redux, Vuex, Zustand）都鼓励使用纯函数（如 Reducers）来更新状态。
*   **性能与纯度折衷:** 虽然纯函数有诸多优点，但在极少数对性能有苛刻要求的场景下，为了避免创建大量新对象/数组，可能会选择有限度的修改，但这通常需要小心权衡和处理。

## 5. 参考资料 (References)

*   **MDN Web Docs: 函数式编程 (Functional programming)**: [https://developer.mozilla.org/zh-CN/docs/Glossary/Functional_programming](https://developer.mozilla.org/zh-CN/docs/Glossary/Functional_programming)
*   **React Docs: Thinking in React (章节中隐含了纯函数的概念)**: [https://react.dev/learn/thinking-in-react](https://react.dev/learn/thinking-in-react) (React 组件应像纯函数一样，接收 props 作为输入，返回 JSX 作为输出，而不改变 props 或外部状态)
*   **维基百科: 纯函数**: [https://zh.wikipedia.org/wiki/%E7%B4%94%E5%87%BD%E6%95%B8](https://zh.wikipedia.org/wiki/%E7%B4%94%E5%87%BD%E6%95%B8) (提供形式化定义)
*   **维基百科: 副作用 (计算机科学)**: [https://zh.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_(%E9%9B%BB%E8%85%A6%E7%A7%91%E5%AD%B8)](https://zh.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_(%E9%9B%BB%E8%85%A6%E7%A7%91%E5%AD%B8))

---