DrillLab
第 28 / 105 道28 / 105 · #293

什么是纯函数

What is a pure function

先自己答,再往下看Answer it yourself first

一句话:两个条件。同样的输入永远给同样的输出; ② 没有副作用(不改外部变量、 不改参数、不发请求、不写 DOM、不打日志)。

不纯的常见来源:Math.random()new Date()、 读写全局变量、arr.push() 改了传进来的数组、console.log

为什么面试爱问:纯函数好测(给输入断输出,不用搭环境)、好缓存(输入一样就能复用结果, 这就是 memoization)、好并发(没有共享状态就没有竞争)。

直接连到 React:

  • 组件的渲染函数必须是纯的—— 同样的 props 和 state 要渲染出同样的 UI。 这是 StrictMode 故意渲染两次能发现问题的原因(见 #332)。
  • Redux 的 reducer 必须是纯的—— 不然时间旅行调试和重放就不成立(见 #352)。
  • 不可变更新之所以是铁律, 就是因为「改传进来的数组」会让函数不纯。

会追问:「那副作用写哪?」—— React 里写useEffect, Redux 里写中间件(thunk / saga)。把纯逻辑和副作用分开是这套设计的核心。

In one line: two conditions. the same input always produces the same output; ② no side effects (it does not touch outer variables, mutate its arguments, fire requests, write to the DOM, or log).

Where impurity usually creeps in: Math.random(), new Date(), reading or writing globals, an arr.push() on the array you were handed, and console.log.

Why interviewers like this one: pure functions are easy to test (give input, assert output, no setup), easy to cache (same input, reuse the result — that is memoization), and easy to run concurrently (no shared state means no races).

Straight into React:

  • A component’s render function must be pure — the same props and state have to produce the same UI. That is why StrictMode renders twice on purpose and catches things (see #332).
  • A Redux reducer must be pure — otherwise time-travel debugging and replay do not hold up (see #352).
  • Immutable updates are a hard rule precisely because mutating the array you were given makes the function impure.

Follow-up: “So where do the side effects go? ” — useEffect in React, middleware (thunk or saga) in Redux. Keeping pure logic and side effects apart is the core of that design.

JavaScript怎么把不纯改纯How to turn an impure function into a pure one示意Illustrative
1// ✗ 不纯:改了传进来的数组
2function addItem(list, item) {
3 list.push(item);
4 return list;
5}
6
7// ✓ 纯:返回新数组
8function addItem(list, item) {
9 return [...list, item];
10}
11
12// ✗ 不纯:输出取决于外部
13let rate = 0.1;
14const tax = (n) => n * rate;
15
16// ✓ 纯:所有依赖都从参数进来
17const tax = (n, rate) => n * rate;
1// ✗ Impure: it changes the array that was passed in
2function addItem(list, item) {
3 list.push(item);
4 return list;
5}
6
7// ✓ Pure: it returns a new array
8function addItem(list, item) {
9 return [...list, item];
10}
11
12// ✗ Impure: the output depends on something outside
13let rate = 0.1;
14const tax = (n) => n * rate;
15
16// ✓ Pure: every input arrives as a parameter
17const tax = (n, rate) => n * rate;