本文档详细介绍了 JavaScript 中管理函数行为的最佳实践,涵盖了单一职责、避免副作用和处理条件逻辑等原则。有关函数参数和形参的信息,请参阅 函数参数。
干净的函数遵循几个核心行为原则,这些原则使代码更易于阅读、维护和测试。这些原则构成了 JavaScript 应用程序中优秀函数设计的基础。
来源:README.md290-322 README.md595-696 README.md355-422 README.md800-907 README.md427-507 README.md1006-1035
单一职责原则 (SRP) 可能是函数设计中最重要的规则。函数应该只做一件事,并做好。这使得它们更容易理解、测试和维护。
当函数具有单一职责时
坏例子:一个同时获取客户数据并发送电子邮件的函数违反了 SRP。
好例子:分解为专用函数——一个用于过滤活动客户,另一个用于实际的电子邮件发送过程。
副作用会使函数变得不可预测且更难测试。纯函数接收输入并返回输出,而不修改外部状态。
修改输入参数
修改全局状态
意外的状态变异
Object.assign() 的方法来创建副本处理数组和对象(可变数据类型)时,请始终创建新的副本,而不是直接修改输入。
不良实践
良好实践
函数应在一致的抽象级别上运行,并得到妥善组织,以创建可读的代码。
一致的抽象级别
函数命名
函数组织
来源:README.md355-422 README.md427-507
条件逻辑会迅速使函数变得复杂。干净的函数以保持清晰度和单一职责的方式处理条件。
将复杂的条件逻辑提取到具有描述性名称的函数中
坏
良好
在处理基于类型或属性的不同行为时,优先选择多态(使用类继承或对象组合),而不是复杂的 if/switch 语句。
示例:与其使用 switch 语句根据飞机类型确定飞行高度计算,不如为每种飞机类型创建专用类,并让它们各自实现高度计算方法。
JavaScript 支持函数式编程概念,这些概念可以带来更干净、更易于维护的代码。
| 函数式方法 | 命令式方法 |
|---|---|
| 声明式风格 | 过程式风格 |
| 使用 map、filter、reduce 等数组方法 | 使用循环并变异变量 |
| 最小化状态更改 | 经常修改外部状态 |
| 强调做什么 | 强调如何做 |
| 更易于测试 | 更难测试 |
命令式(坏)
函数式(好)
删除不再使用的代码,而不是将其注释掉。Git 等版本控制系统会保存您的历史记录,因此无需在注释中保留未使用的代码。
过早优化会导致代码更复杂、可读性更差。现代 JavaScript 引擎已经优化了许多常见模式。
| 模式 | 反模式 | 为什么很重要 |
|---|---|---|
| 函数只做一件事 | 具有多重职责的函数 | 更易于测试、理解和维护 |
| 没有副作用的纯函数 | 修改外部状态的函数 | 可预测的行为,易于调试 |
| 一致的抽象级别 | 混合高低级别操作 | 更清晰的代码组织 |
| 封装的条件 | 复杂的内联条件 | 自文档化代码 |
| 描述性的函数名 | 模糊或误导性的名称 | 降低读者的认知负担 |
| 使用多态处理特定类型的行为 | 大型 switch/if 语句 | 更具扩展性的设计 |
| 使用默认对象 | 手动属性检查 | 更简洁,不易出错 |
| 函数式编程方法 | 命令式状态变异 | 不易因状态更改而出错 |
函数行为是干净代码的关键方面。通过关注单一职责、避免副作用、保持一致的抽象级别以及妥善处理条件,您可以创建更容易理解、测试和维护的函数。
本文档中概述的原则为编写干净函数奠定了基础,这将使代码库随着时间的推移更易于维护,并减少处理代码的开发人员的认知负担。