Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >函数组件 和 函数式编程 有关系么?

函数组件 和 函数式编程 有关系么?

作者头像
公众号@魔术师卡颂
发布于 2023-11-22 11:05:58
发布于 2023-11-22 11:05:58
27600
代码可运行
举报
文章被收录于专栏:魔术师卡颂魔术师卡颂
运行总次数:0
代码可运行

大家好,我卡颂。

长期使用React的同学应该知道,React中存在两种组件:

  • Class Component,类组件
  • Function Component,函数组件

既然提到「类」「函数」,那么很自然的,我们会进一步思考:

  • 类组件和OOP(面向对象编程)有关系么?
  • 函数组件和FP(函数式编程)有关系么?

毕竟,如果类组件和OOP有关,那么OOP中的思想(继承、封装、多态...)也能指导类组件的业务开发(函数组件与FP的关系同理)。换言之,我们可以直接用这些编程范式的最佳实践指导React项目开发。

那么,「函数组件」「函数式编程」究竟是什么关系呢?本文会围绕这个话题展开讲解。

编程范式与DSL

首先,我们应该明确,「框架语法」本质是一种DSL(领域相关语言),他是为了「某个特定领域的开发」量身定制的。

比如,React作为一款针对「view开发」DSL,虽然不同的view使用的框架不同,比如:

  • 对于web,框架为ReactDOM
  • 对于小程序,框架为Taro
  • 对于原生开发,字节内部有个叫React Lynx的框架

但这些框架都大体遵循同一套DSLReact语法),这套DSL并不属于某一种编程范式,而应该被视为「不同编程范式中,更符合view开发的语言特性的集合」

所以,作为React DSL的一部分,函数组件可以体现OOP的思想,类组件也能体现FP的思想。只要这些思想有利于「view开发」,就可以纳入DSL的语法中。

比如,下面的函数组件Header,是由WelcomeMessageLogoutButton组件组合而成,这是OOP中的「组合优于继承」思想:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Header(props) {
  return (
    <div>
      <WelcomeMessage name={props.name} />
      <LogoutButton onClick={props.onLogout} />
    </div>
  );
}

再比如,下面的类组件Cpn中,要改变状态count,并不是通过突变(类似this.state.count++),而是调用this.setState,传入不可变数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Cpn extends React.Component {
  // ...
  onClick() {
    const count = this.state.count;
    this.setState({count: count + 1});
  }
  render() {
    // ...
  }
}

「使用不可变数据」属于FP中的思想。

所以,当我们要深入了解某个React特性时,应该以如下顺序递进的思考:

  1. React的开发理念是什么?
  2. 为了实现这套理念,吸收了哪些编程范式中的思想
  3. 这些思想如何在React中落地

如果我们用上述思考过程研究「函数组件与函数式编程的关系」,会发现:

  • 函数组件属于落地的产物(上述思考的第三步)
  • 函数式编程属于编程范式(上述思考的第二步)

这就是两者的关系 —— 函数组件属于多种编程范式(主要是OOPFP)在React中最终的落地产物,其中借鉴了一部分FP的思想。

我们不应该将函数组件单纯视为FPReact中的具象体现。

那么,函数组件究竟是如何演进而来的呢?

函数组件的演进

让我们按照上述三步演进顺序思考。首先,React的开发理念践行了如下公式(即:UI是数据快照经过函数映射而来):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
UI = fn(snapshot)

要落地这个理念,有两个要素需要实现:

  • 数据快照
  • 函数映射

在这里,FP「不可变数据」更适合作为「数据快照」的载体,所以React中状态是不可变的,因为状态的本质是快照。

「函数映射」的载体则没有特殊要求。在React中,每次触发更新,所有组件都会重新renderrender的过程就是「函数映射」的过程,输入是propsstate,输出是JSX

React相对的,Vue中组件则更符合OOP的理念,考虑如下App组件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const App = {
  setup(initialProps) {
    const count = reactive({count: 0})
    const add = () => { count.value++ }
    return {count, add}
  }
  template: "...省略"
}

组件的setup方法只会在初始化时执行一次,后续触发更新时操作的都是同一个闭包中的数据。这里面的闭包就是OOP思想中的实例。

既然React「函数映射」的载体没有特殊要求,那么类组件、函数组件都是可以的。

那为什么函数组件最终替代了类组件成为React开发的主流呢?很多同学认为「函数组件的Hooks可以更好的复用逻辑」这一点,是函数组件优于类组件的主要原因。

但实际上,基于装饰器的类开发模式早已被验证是优秀的逻辑复用模式,类组件配合TS装饰器的模式是行得通的。

主要原因还是 —— 函数组件能够更好的落地UI = fn(snapshot)这一理念。

刚才说过,公式中的snapshot「快照」的含义。在React中,快照主要包括三类数据:

  • state
  • props
  • context

对于同一个组件,根据公式UI = fn(snapshot),相同的快照输入应该获得相同输出(JSX)。

但状态更新也可能触发「副作用」,比如请求数据、操作DOM...

在类组件中,这些「副作用」逻辑被分散在各个生命周期钩子函数中,React无法掌控。

而在函数组件中:

  • 副作用受限在useEffect中。每次renderReact都会保证上次的副作用效果已经被清除(通过useEffect回调的返回值函数)
  • ref的传播也需要借由forwardRef,这进一步限制了ref可能的影响范围
  • 数据请求的副作用被交给Suspense处理,考虑下面组件:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function UserList({id}) {
  // 异步请求数据
  const data = use(fetchUser(id));
  
  // ...
}

使用时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Suspense fallback={<div>加载中...</div>}>
  <UserList id={1}/>
</Suspense>

总而言之,使用函数组件时,所有副作用都处于一种「受到管控」的状态,可以尽可能保证每次更新时「相同的快照输入,获得相同的JSX输出」,所以函数组件在React中才会发扬光大。

同时,这也契合了FP中的纯函数思想。

总结

「函数组件」并不是「函数式编程」React中的具体实现,而是React的设计理念UI = fn(snapshot)落地的最好载体。

React中,还吸收了其他编程范式中的优秀思想。FP只是其中影响React最深的一种。毕竟,一切落地都是为了践行最初的设计理念。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 魔术师卡颂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
浅析函数式编程
高中一年级,应该是最早接触函数这个概念的时间,印象很深刻,毕竟是高考压轴大题,但它却是必修一第二章的内容。
石的三次方
2022/05/16
2550
浅析函数式编程
前端开发者的 Kotlin 之旅:函数式编程深入
纯函数是函数式编程的核心概念:给定相同输入总是返回相同输出,且没有副作用。这使得代码更可预测、更易测试,也更容易进行并行处理。
骑猪耍太极
2025/05/14
410
前端开发者的 Kotlin 之旅:函数式编程深入
函数式编程概要
函数式编程是一种通过组合纯函数来编写软件的编程范式,它是声明式而非命令式的,其原则是避免共享状态, 改变数据,以及副作用。
宅蓝三木
2024/10/09
1070
函数式编程漫谈
最近在思考一个问题,函数式编程对于我们的软件开发的意义到底有多大?到底值不值得我们花时间去学习。因此,写下这篇文章来记录自己的思考。文章包含了前后端开发中的一些内容,大家各自选择阅读。
100000798482
2018/08/20
9980
函数式编程漫谈
前端中的函数式编程
导语 前端的技术革新从来没有停止过,但从最近的趋势来看,貌似有一个“新”名词出现,那就是函数式编程(FP,functional programming)。vue、react这些热门的框架都多多少少有点
陈柏信
2017/08/30
1.6K0
《现代Javascript高级教程》JavaScript函数式编程
函数式编程(Functional Programming)是一种编程范式,它将计算机程序视为数学函数的组合,强调函数的纯粹性和不可变性。JavaScript作为一种多范式的语言,也支持函数式编程风格。本文将介绍JavaScript函数式编程的基本概念和特点,并通过代码示例来展示其实际应用。
linwu
2023/07/27
2100
用 Kotlin 的函数式编程 替代 GOF 设计模式用 Kotlin 的函数式编程 替代 GOF 设计模式函数式编程(FP)《Kotlin极简教程》正式上架:
"函数式编程", 又称泛函编程, 是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。它的基础是 λ 演算(lambda calculus)。λ演算可以接受函数当作输入(参数)和输出(返回值)。
一个会写诗的程序员
2018/08/17
1.2K0
用 Kotlin 的函数式编程 替代 GOF 设计模式用 Kotlin 的函数式编程 替代 GOF 设计模式函数式编程(FP)《Kotlin极简教程》正式上架:
函数式编程,真香
最开始接触函数式编程的时候是在小米工作的时候,那个时候看老大以前写的代码各种 compose,然后一些 ramda 的一些工具函数,看着很吃力,然后极力吐槽函数式编程,现在回想起来,那个时候的自己真的是见识短浅,只想说,'真香'。
桃翁
2018/12/28
8470
函数式编程,真香
Js-函数式编程 前言什么是函数式编程为什么Js支持FP纯函数柯里化组合 compose范畴学functorMonadApplicative FunctorFunctor\Monad\Applic
JavaScript是一门多范式语言,即可使用OOP(面向对象),也可以使用FP(函数式),由于笔者最近在学习React相关的技术栈,想进一步深入了解其思想,所以学习了一些FP相关的知识点,本文纯属个人的读书笔记,如果有错误,望轻喷且提点。
菜的黑人牙膏
2019/04/09
1.8K0
Js-函数式编程
		前言什么是函数式编程为什么Js支持FP纯函数柯里化组合 compose范畴学functorMonadApplicative FunctorFunctor\Monad\Applic
面向函数编程:关于函数式组件、dialog的api化
createElement函数, 三个参数, 第一个参数是html标签或自定义组件,第二个参数一个obj(包含props, on...等等), 第三个参数children(通过createElement构建, 或者字符串)
默默的成长
2022/10/29
4920
【JS】394- 简明 JavaScript 函数式编程-入门篇
本文较长,总共分为三大部分:(对于函数式编程以及其优点有一定理解的童鞋,可以直接从 第二部分 开始阅读)
pingan8787
2019/10/30
1.1K0
【JS】394- 简明 JavaScript 函数式编程-入门篇
深入理解函数式编程(下)
函数式编程是一种历史悠久的编程范式。作为演算法,它的历史可以追溯到现代计算机诞生之前的λ演算,本文希望带大家快速了解函数式编程的历史、基础技术、重要特性和实践法则。
美团技术团队
2022/12/16
1K0
深入理解函数式编程(下)
立等可取的 Vue + Typescript 函数式组件实战
不同于面向对象编程(OOP)中通过抽象出各种对象并注重其间的解耦问题等,函数式编程(FP) 聚焦最小的单项操作,将复杂任务变成一次次 f(x) = y 式的函数运算叠加。函数是 FP 中的一等公民(First-class object),可以被当成函数参数或被函数返回;同时,这些函数应该不依赖或影响外部状态,这意味着对于给定的输入,将产生相同的输出。
江米小枣
2020/11/04
2.4K0
立等可取的 Vue + Typescript 函数式组件实战
鹅厂原创 | 前端中的函数式编程
0写在前面  前端的技术革新从来没有停止过,但从最近的趋势来看,貌似有一个“新”名词出现,那就是函数式编程(FP,functional programming)。 vue、react这些热门的框架都多多少少有点涉及到函数式编程的领域,甚至已经开始有一些以函数式编程作为主范式的框架出现,比如说cyclejs。 那么,为什么函数式编程会如此重要呢? 或许我们可以先从函数式编程的认识聊起。 1何为函数式编程? 1.1 什么是纯函数? 让我们回想一下初中数学 我们知道一个函数有定义域和值域,对于定义域里面的每
用户1097444
2022/06/29
8430
鹅厂原创 | 前端中的函数式编程
函数式编程:提高代码质量的新范式
随着计算机科学的发展,编程语言也在不断地演进和发展。其中,函数式编程作为一种新的编程范式,越来越受到开发者的关注。函数式编程强调函数的纯粹性和不变性,通过使用高阶函数、闭包、柯里化、函数组合等技术,可以提高代码的可维护性、可读性和可测试性。本文将详细介绍函数式编程的概念、特点和实现方法,以及如何在实际开发中使用函数式编程来提高代码质量。
Front_Yue
2023/12/28
3960
函数式编程:提高代码质量的新范式
2023年再看函数式编程
最初接触函数式编程还是Rx 系列响应式的概念带来的,这么多年用过Rxswift,Rxjs ,一直理解不够深刻。 React 带来的hooks, 官方概念是利用函数式编程方式,更好的组合,开发和测试。但是还是觉得不够深刻,又看了些资料,梳理下自己的理解,重点关注react 中的提现。
星宇大前端
2023/11/30
1800
面向对象变成VS函数式编程
面向对象编程(OOP)和函数式编程(FP)是软件开发中的两种主要范式。这两种方法都为组织、设计和实现软件系统提供了不同的方法论。虽然面向对象编程几十年来一直是主导范式,但函数式编程近年来获得了巨大的吸引力,这要归功于其处理状态和数据的独特方法。我们将学习研究每种范式的特征,检查它们的优缺点。并用Java来演示两者的差异。
FunTester
2024/05/28
1440
面向对象变成VS函数式编程
Kotlin 函数式编程思想 FP in KotlinKotlin
函数编程支持函数作为第一类对象,有时称为闭包或者仿函数(functor)对象。实质上,闭包是起函数的作用并可以像对象一样操作的对象。与此类似,FP 语言支持高阶函数。高阶函数可以用另一个函数(间接地,用一个表达式) 作为其输入参数,在某些情况下,它甚至返回一个函数作为其输出参数。这两种结构结合在一起使得可以用优雅的方式进行模块化编程,这是使用 FP 的最大好处。 [4]
一个会写诗的程序员
2021/12/16
3610
Kotlin 函数式编程思想 FP in KotlinKotlin
了解 JavaScript 函数式编程
而我们今天要讨论的编程范式 -- 函数式编程把事物和事物直接的联系抽象到程序世界,强调的是函数的计算,对运算过程进行抽象。使用函数进行编程。
Jimmy_is_jimmy
2022/04/24
3510
函数式编程能有多优雅?
函数式编程,想必大家多少都听说过这个概念,那么到底什么是函数式编程?函数式编程到底有什么优势?这篇文章我们就来一探究竟
闫同学
2024/08/08
4090
推荐阅读
相关推荐
浅析函数式编程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验