函数式编程 vs 面向对象:比较范式,查看实用代码示例,并学习如何为你的项目选择最佳方法。
December 2, 2025 (4mo ago)
函数式编程 vs 面向对象:快速指南
函数式编程 vs 面向对象:比较范式,查看实用代码示例,并学习如何为你的项目选择最佳方法。
← Back to blog
函数式编程 vs 面向对象:快速指南
functional programming vs object oriented: Compare paradigms, see practical code examples, and learn how to choose the best approach for your project.

介绍
函数式编程与面向对象编程之间的真正差异归结为一个关注点问题:你是围绕“你做什么”来组织代码,还是围绕“谁来做”来组织代码?函数式编程(FP)强调你在做什么,将软件视为无状态、数学函数调用的链条。面向对象编程(OOP)强调谁在做这件事,将逻辑组织在相互交互的有状态对象周围。本指南比较了两种范式,展示了实用的 TypeScript 和 React 示例,并帮助你为项目选择最佳方法。
快速看一下 FP 与 OOP
在函数式和面向对象风格之间做选择不仅仅是一个技术决定,它是一种用于构建软件和处理数据流的思维方式的承诺。这个高层比较为具体示例和实际权衡奠定了基础。
核心哲学差异
OOP 通过将数据和对其操作的函数捆绑到对象中来建模世界。想象一个 User 对象,它保存像姓名和电子邮件这样的数据,并暴露诸如 updateEmail() 或 sendPasswordReset() 之类的方法。每个对象管理它自己的状态。
FP 则采取相反的方法,将数据与行为分离。数据往往是不可变的,纯函数接收输入并返回新的输出而不产生副作用。这减少了在大型 OOP 系统中可能出现的共享状态的纠缠网络。
“以后推理代码才是真正的挑战。FP 将移动部件最小化,而 OOP 将这些部件组织成可理解的组件。”
许多现代团队从两种范式中借鉴思想,以获得两全其美的效果。首先,这里是基本差异的快速总结。
函数式编程与面向对象编程的核心差异
| Concept | Functional Programming (FP) | Object-Oriented Programming (OOP) |
|---|---|---|
| Primary Unit | Functions | Objects |
| State Management | Immutable state | Mutable state |
| Data & Operations | Kept separate | Encapsulated together |
| Concurrency | Easier to handle, stateless | Requires explicit locks or synchronization |
| Flow Control | Function calls and composition | Methods, loops, and conditionals |
| Key Principles | Pure functions, immutability | Encapsulation, inheritance, polymorphism |
理解核心理念
这些范式不仅仅是语法选择;它们是关于数据、行为以及如何构建系统的思维方式。哪个更适合你的项目取决于你希望如何管理变化和复杂性。

函数式编程范式
FP 追溯到 λ 演算,将计算视为数学函数的求值。纯函数(对相同输入总是返回相同输出且不产生副作用)是核心。不可变性防止就地更改,鼓励返回新值。
这种可预测性使 FP 代码更容易测试和推理,尤其是在共享可变状态经常导致错误的并发系统中。FP 的单向数据流也倾向于生成更清晰的数据转换流水线。
面向对象编程范式
OOP 将系统建模为封装了状态和行为的交互对象。封装隐藏内部细节,使对象向系统其余部分呈现简单的接口。继承和多态支持代码复用和灵活的抽象。
这种方法非常适合建模复杂的领域实体及其交互。当领域概念稳定且对象关系自然地映射到业务规则时,OOP 可以产生直观且易维护的设计。
可维护性与可扩展性的比较
选择一种范式会影响长期维护和系统的扩展方式。FP 和 OOP 都提供了有价值的策略,但它们处理复杂性的方式不同。
可维护性:可预测性与封装
FP 通过纯函数和不可变性优先考虑可预测性。一个对相同输入始终返回相同结果的函数很容易测试和隔离。OOP 将相关的数据和行为组织在一起,这有助于开发者通过检查自包含的组件来推理系统。
权衡在于:FP 的清晰性来自于将数据与行为分离,而 OOP 的清晰性来自于将它们组合在一起。这会影响调试流程——FP 通常将 bug 缩小到特定函数,而 OOP 可能需要追踪多个对象之间的交互。
可扩展性:并发与并行
FP 的无状态方法简化了并发和并行处理,因为纯函数不会修改共享数据。这减少了对锁和同步的需求。OOP 可以实现并发,但通常需要小心的状态管理和同步机制以避免竞态条件。
FP 在需要可预测并发行为的领域中越来越受欢迎,尽管主流开发者的采用率仍集中在多范式和面向对象语言上 1.2
现实示例:TypeScript 与 React
下面我们用两种风格构建相同的用户设置表单:经典的 React 类组件(OOP)和使用 Hooks 的现代函数组件(FP 风格)。这突出显示了架构选择如何影响状态处理、逻辑重用和结构。

OOP 方法:React 类组件
类组件将状态和方法组合到单个对象中,这符合 OOP 的封装模型。
import React, { Component } from 'react';
interface UserSettings {
name: string;
email: string;
}
class UserSettingsForm extends Component<{}, UserSettings> {
state = {
name: 'Jane Doe',
email: 'jane.doe@example.com',
};
handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
this.setState({ [name]: value } as Pick<UserSettings, keyof UserSettings>);
};
handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
console.log('Submitting data:', this.state);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input name="name" value={this.state.name} onChange={this.handleChange} />
<input name="email" value={this.state.email} onChange={this.handleChange} />
<button type="submit">Save Settings</button>
</form>
);
}
}
这种模式将相关数据和行为保留在一起,但较大的组件如果不使用高阶组件(higher-order components)等附加模式,可能会变得更难重构和重用。
函数式重构:Hooks 与纯辅助函数
函数式方法将状态与纯函数分离,使各个部分更容易测试和重用。
import React, { useState } from 'react';
const formatUserDataForApi = (name: string, email: string) => ({
userName: name,
userEmail: email,
});
const UserSettingsFormFunctional = () => {
const [name, setName] = useState('Jane Doe');
const [email, setEmail] = useState('jane.doe@example.com');
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
if (name === 'name') {
setName(value);
} else {
setEmail(value);
}
};
const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
const payload = formatUserDataForApi(name, email);
console.log('Submitting data:', payload);
};
return (
<form onSubmit={handleSubmit}>
<input name="name" value={name} onChange={handleChange} />
<input name="email" value={email} onChange={handleChange} />
<button type="submit">Save Settings</button>
</form>
);
};
React 的 Hooks 通过在函数中启用状态和副作用,使这种风格成为主流,并且它们在现代 React 开发中被广泛采纳 3。
如何选择正确的范式
这不是一场必须分出输赢的对抗。正确的选择取决于你的团队、问题领域和长期目标。使用以下要点来指导务实的决策。
何时选择 OOP
当你需要建模具有持久状态和行为的丰富领域实体时,选择 OOP,例如:
- 拥有许多相互关联模块的大型企业系统
- 组件级状态自然映射到对象的丰富、有状态的 UI 组件
- 领域具有稳定且定义明确的实体
何时选择 FP
当可预测性、并发和数据转换是优先事项时,选择 FP,例如:
- 数据处理流水线和 ETL 任务
- 并发或并行系统中状态同步代价高昂的场景
- 函数能干净地映射到算法的数学或科学计算
实用决策清单
- 你的数据本质如何:是有状态对象还是可变换的流?
- 并发对性能和正确性有多关键?
- 你的团队具有什么样的专长以及学习新模式的意愿如何?
- 是否可以采用混合方法而不强行使用单一范式?
采用混合方法
大多数成功的系统结合了两种范式。像 TypeScript 和 Python 这样的多范式语言允许你在类内部使用不可变数据,对集合应用 map 和 filter,并为核心业务逻辑隔离纯函数。
在实践中结合范式
常见的混合模式:
- 类内部的不可变状态:方法返回新实例而不是修改内部状态。
- 服务使用纯函数:以无状态函数实现业务逻辑,接受输入并返回输出。
- 函数式集合方法:使用
map、filter、reduce处理数组,而不是使用有状态的循环。
用对象来建模“事物”,用纯函数来协调它们之间的行为。这样的分离提高了清晰度和可测试性。

常见问题
函数式编程比面向对象编程更快吗?
性能取决于问题、语言和运行时。FP 的不可变性可能增加分配开销,但其无状态特性简化了并发,可能在并行系统中提高吞吐量。依赖就地更新的单线程任务可能在 OOP 风格的可变操作下运行得更快。
我可以混合使用函数式和面向对象代码吗?
可以。混合范式很常见,通常也是最实用的选择。用对象建模核心实体,同时将复杂逻辑表达为纯函数。
初学者应该先学哪种范式?
OOP 往往更容易初学,因为类和对象直观地映射到现实世界概念。及早学习核心函数式思想——纯函数和不可变性——可以培养有助于提高代码质量的习惯。
底线建议
- 将范式与问题匹配。对于可预测的数据转换和并发使用 FP。对于丰富的领域建模使用 OOP。
- 对核心逻辑优先使用小而纯的函数。保持组件和类专注且小型化。
- 在有用的地方采用混合方法。你不必对整个代码库只采用一种范式。
实用问答
问:我如何为现有代码库在 FP 与 OOP 之间做决定?
答:评估最大的痛点。如果 bug 来自共享的可变状态,则引入不可变性和纯函数。如果领域天然基于对象,则保留对象但提取无状态服务。
问:如何在 OOP 项目中安全地引入 FP 原则?
答:从小型、可测试的服务开始,以纯函数实现,添加函数式数组方法,并考虑返回新对象实例而不是修改状态。
问:有哪些快速方法可以立即提高可维护性?
答:强制使用小函数,为纯逻辑添加自动化测试,使用 map/filter 代替有副作用的循环,并为有状态对象记录不变式。
AI编写代码。您让它持久。
在AI加速的时代,干净代码不仅仅是好的实践 — 它是能够扩展的系统与在自己的重量下崩溃的代码库之间的区别。