跳转到内容

JavaScript纯函数:修订间差异

来自代码酷
Admin留言 | 贡献
Page creation by admin bot
 
Admin留言 | 贡献
Page update by admin bot
 
第1行: 第1行:
= JavaScript纯函数 =
= JavaScript纯函数 =


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


== 定义与特性 ==
1. '''相同的输入始终返回相同的输出'''(确定性)
纯函数必须满足以下两个条件:
2. '''不产生副作用'''(不会修改外部状态)
# '''确定性''':给定相同的输入,总是返回相同的输出。
# '''无副作用''':不会修改任何外部状态(如全局变量、传入的参数等),也不会产生可观察的副作用(如网络请求、DOM操作等)。


数学上,纯函数可以表示为:
== 特性详解 ==
<math>f(x) = y</math>
 
其中,函数 <math>f</math> 对于相同的 <math>x</math> 总是返回相同的 <math>y</math>。
=== 1. 确定性 ===
纯函数在给定相同输入时,总是返回相同的结果,不受外部状态影响。数学函数就是典型的纯函数,例如:


=== 示例:纯函数与非纯函数 ===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
// 纯函数示例
// 纯函数示例
function add(a, b) {
function square(x) {
     return a + b;
     return x * x;
}
}


console.log(add(2, 3)); // 输出:5(始终相同)
console.log(square(5)); // 输出: 25 (无论调用多少次,结果都相同)
</syntaxhighlight>
 
=== 2. 无副作用 ===
纯函数不会修改任何外部状态,包括:
* 不修改传入的参数
* 不修改全局变量
* 不进行I/O操作(如网络请求、文件读写)
* 不调用非纯函数(如`Math.random()`或`Date.now()`)


// 非纯函数示例(依赖外部变量)
<syntaxhighlight lang="javascript">
// 非纯函数示例(有副作用)
let counter = 0;
let counter = 0;
function increment() {
function increment() {
     counter++; // 修改外部状态
     counter++; // 修改了外部变量
     return counter;
     return counter;
}
}


console.log(increment()); // 输出:1(但下次调用可能不同)
// 纯函数版本
function pureIncrement(num) {
    return num + 1; // 不修改外部状态
}
</syntaxhighlight>
</syntaxhighlight>


== 为什么使用纯函数? ==
== 纯函数 vs 非纯函数 ==
纯函数具有以下优势:
 
* '''可预测性''':相同的输入总是产生相同的输出。
<mermaid>
* '''可测试性''':无需依赖外部状态,测试更简单。
flowchart LR
* '''可缓存性'''(Memoization):可以缓存函数结果以提高性能。
    A[函数] --> B[纯函数]
* '''并行安全''':纯函数不会因并发执行而产生竞态条件(Race Condition)。
    A --> C[非纯函数]
    B --> D[确定性]
    B --> E[无副作用]
    C --> F[可能依赖外部状态]
    C --> G[可能有副作用]
</mermaid>


== 实际应用案例 ==
== 实际应用案例 ==
=== 1. 数据处理与转换 ===
 
纯函数常用于数据转换,例如数组操作:
=== 1. 数据处理 ===
纯函数非常适合数据转换场景:
 
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
const numbers = [1, 2, 3, 4];
// 购物车价格计算(纯函数实现)
function calculateTotal(cartItems) {
    return cartItems.reduce((total, item) => {
        return total + (item.price * item.quantity);
    }, 0);
}


// 纯函数:map 不会修改原数组
const cart = [
const doubled = numbers.map(x => x * 2);
    { name: "Book", price: 10, quantity: 2 },
console.log(doubled); // [2, 4, 6, 8]
    { name: "Pen", price: 2, quantity: 5 }
];
 
console.log(calculateTotal(cart)); // 输出: 30
</syntaxhighlight>
</syntaxhighlight>


=== 2. Redux 中的 Reducer ===
=== 2. React组件 ===
在 Redux 中,Reducer 必须是纯函数:
React推崇使用纯函数组件:
 
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
function counterReducer(state = 0, action) {
// React纯函数组件
     switch (action.type) {
function Welcome(props) {
        case 'INCREMENT':
     return <h1>Hello, {props.name}</h1>;
            return state + 1; // 返回新状态,而非修改原状态
        default:
            return state;
    }
}
}
</syntaxhighlight>
</syntaxhighlight>


== 如何编写纯函数 ==
== 数学表示 ==
1. '''避免修改参数''':直接修改传入的对象或数组会使其成为非纯函数。
 
2. '''避免依赖全局状态''':使用参数传递所需数据。
纯函数可以用数学函数表示:
3. '''隔离副作用''':将副作用(如API调用)与纯逻辑分离。
<math>
f(x) = y
</math>
其中:
* <math>x</math> 是输入
* <math>y</math> 是输出
* 对于相同的 <math>x</math>,总是得到相同的 <math>y</math>
 
== 优点 ==
 
* '''可预测性''':结果只依赖输入,易于推理
* '''可测试性''':不需要复杂的环境设置
* '''可缓存性''':可以记忆化(memoize)结果
* '''并行安全''':无共享状态,可安全并行执行
 
== 注意事项 ==
 
虽然纯函数有很多优点,但在实际开发中:
1. 应用不可能完全由纯函数组成(需要I/O等副作用)
2. 合理组合纯函数和非纯函数
3. 将副作用限制在可控范围内
 
== 练习示例 ==
 
将以下非纯函数转换为纯函数:


=== 示例:避免参数修改 ===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
// 非纯函数(修改参数)
// 原始版本(非纯)
function updateUserImpure(user) {
let discount = 0.1;
    user.age = 30; // 直接修改参数
function applyDiscount(price) {
     return user;
     return price * (1 - discount);
}
}


// 纯函数(返回新对象)
// 纯函数版本
function updateUserPure(user) {
function pureApplyDiscount(price, discountRate) {
     return { ...user, age: 30 }; // 使用展开运算符创建新对象
     return price * (1 - discountRate);
}
}
</syntaxhighlight>
</syntaxhighlight>
== 纯函数的局限性 ==
纯函数无法处理以下场景:
* 需要与外部系统交互(如数据库、API调用)。
* 需要修改DOM或浏览器状态。
* 需要随机数生成(如 `Math.random()`)。


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


=== 对比图表 ===
纯函数是JavaScript函数式编程的基石,它们通过限制副作用和提高确定性使代码更可靠。虽然实际应用中需要与非纯函数配合使用,但尽可能多地使用纯函数能显著提高代码质量。
<mermaid>
pie
    title 纯函数 vs 非纯函数
    "确定性" : 40
    "无副作用" : 40
    "可测试性" : 20
</mermaid>
 
== 练习 ==
尝试将以下非纯函数改写为纯函数:
<syntaxhighlight lang="javascript">
let total = 0;
function addToTotal(value) {
    total += value;
    return total;
}
</syntaxhighlight>


[[Category:编程语言]]
[[Category:编程语言]]
[[Category:JavaScript]]
[[Category:JavaScript]]
[[Category:Javascript函数式编程]]
[[Category:Javascript函数]]

2025年4月30日 (三) 19:07的最新版本

JavaScript纯函数[编辑 | 编辑源代码]

纯函数(Pure Function)是函数式编程中的核心概念之一,也是编写可预测、可维护代码的重要原则。在JavaScript中,纯函数具有以下两个关键特性:

1. 相同的输入始终返回相同的输出(确定性) 2. 不产生副作用(不会修改外部状态)

特性详解[编辑 | 编辑源代码]

1. 确定性[编辑 | 编辑源代码]

纯函数在给定相同输入时,总是返回相同的结果,不受外部状态影响。数学函数就是典型的纯函数,例如:

// 纯函数示例
function square(x) {
    return x * x;
}

console.log(square(5)); // 输出: 25 (无论调用多少次,结果都相同)

2. 无副作用[编辑 | 编辑源代码]

纯函数不会修改任何外部状态,包括:

  • 不修改传入的参数
  • 不修改全局变量
  • 不进行I/O操作(如网络请求、文件读写)
  • 不调用非纯函数(如`Math.random()`或`Date.now()`)
// 非纯函数示例(有副作用)
let counter = 0;
function increment() {
    counter++; // 修改了外部变量
    return counter;
}

// 纯函数版本
function pureIncrement(num) {
    return num + 1; // 不修改外部状态
}

纯函数 vs 非纯函数[编辑 | 编辑源代码]

flowchart LR A[函数] --> B[纯函数] A --> C[非纯函数] B --> D[确定性] B --> E[无副作用] C --> F[可能依赖外部状态] C --> G[可能有副作用]

实际应用案例[编辑 | 编辑源代码]

1. 数据处理[编辑 | 编辑源代码]

纯函数非常适合数据转换场景:

// 购物车价格计算(纯函数实现)
function calculateTotal(cartItems) {
    return cartItems.reduce((total, item) => {
        return total + (item.price * item.quantity);
    }, 0);
}

const cart = [
    { name: "Book", price: 10, quantity: 2 },
    { name: "Pen", price: 2, quantity: 5 }
];

console.log(calculateTotal(cart)); // 输出: 30

2. React组件[编辑 | 编辑源代码]

React推崇使用纯函数组件:

// React纯函数组件
function Welcome(props) {
    return <h1>Hello, {props.name}</h1>;
}

数学表示[编辑 | 编辑源代码]

纯函数可以用数学函数表示: f(x)=y 其中:

  • x 是输入
  • y 是输出
  • 对于相同的 x,总是得到相同的 y

优点[编辑 | 编辑源代码]

  • 可预测性:结果只依赖输入,易于推理
  • 可测试性:不需要复杂的环境设置
  • 可缓存性:可以记忆化(memoize)结果
  • 并行安全:无共享状态,可安全并行执行

注意事项[编辑 | 编辑源代码]

虽然纯函数有很多优点,但在实际开发中: 1. 应用不可能完全由纯函数组成(需要I/O等副作用) 2. 合理组合纯函数和非纯函数 3. 将副作用限制在可控范围内

练习示例[编辑 | 编辑源代码]

将以下非纯函数转换为纯函数:

// 原始版本(非纯)
let discount = 0.1;
function applyDiscount(price) {
    return price * (1 - discount);
}

// 纯函数版本
function pureApplyDiscount(price, discountRate) {
    return price * (1 - discountRate);
}

总结[编辑 | 编辑源代码]

纯函数是JavaScript函数式编程的基石,它们通过限制副作用和提高确定性使代码更可靠。虽然实际应用中需要与非纯函数配合使用,但尽可能多地使用纯函数能显著提高代码质量。