函数式编程之美

2025-05-24

函数式编程之美

编写程序的方法有很多种,或许你已经将程序设计得像一系列命令一样,这就是我们所说的“命令式编程”。又或许,你的程序将事物保存在对象中,并与它们交互,来回发送消息,这就是“面向对象编程”。但今天我要讲的是函数式编程。正如其他人提到的,函数式编程是一种编码风格,它与是否放置、;是否放在{}表达式之后或之后无关,而是与我们如何指示程序执行操作无关。从技术角度来说,这是一种“编程范式”。那么,你为什么要关注它呢?

有趣的功能✨

当我们谈论函数式编程的世界时,一切都是函数。这个概念和我们在学校学习的数学概念太相似了,老师会说这样的话:

函数是值之间的一种特殊关系:它的每个输入值都会返回一个输出值。

来自mathisfun

这个定义非常重要,因为它为我们提供了程序的基础,即纯函数。纯函数是指只依赖于输入的函数,它们不会寻找你世界之外的任何东西,只接收你传入的参数,并且只返回输出,不会影响世界的其他部分。例如,看到这些函数,你能说出第一个函数有什么问题吗?

第一个版本❌


let age = 19

function getMyAge() {
  console.log(`I'm ${age} years old.`)
}

getMyAge(age)
age = 20
getMyAge(age)
Enter fullscreen mode Exit fullscreen mode

第二版✅

function getMyAge(age) {
  return `I'm ${age} years old.`
}

getMyAge(19)
getMyAge(20)
Enter fullscreen mode Exit fullscreen mode

在第一种情况下,函数会查找作用域之外的变量,从而以某种方式改变世界。在这种情况下,理想的情况是只返回值,正如你所注意到的,如果我们使用相同的参数(即使没有参数)调用该函数,我们得到的值也会不同。在纯函数中,这种情况不会发生。
现在,你已经对函数式编程的优点有了基本的了解,但我们还有更多功能,请查看下面的内容💪。

副作用🌊

副作用是在计算过程中与外界发生的任何交互,使用纯函数不会发生这种交互,而且我们的代码可以更加可预测,因为我们的结果仅取决于它的输入,如果我们知道函数是什么样子,以及它接收哪些输入,您就可以预测结果

可变性🐺

可变性指的是事物可以改变,但在函数式编程中,不鼓励使用可变性。当我们拥有不可变数据时,其状态在创建后就无法更改。如果需要更改某些内容,则需要创建一个新的值。

可变示例

function changeFirstElem(array) {
  array[0] = 'Lose yourself to dance'
}

const daftPunkPopSongs = ['Instant Crush', 'Get Lucky', 'One More Time']
changeFirstElem(daftPunkPopSongs)
Enter fullscreen mode Exit fullscreen mode

不可变示例

function changeFirstElem(array) {
  const modifiedArray = ['Lose yourself to dance', ...array]
  return modifiedArray
}

const daftPunkPopSongs = ['Instant Crush', 'Get Lucky', 'One More Time']
const modifiedArray = changeFirstElem(daftPunkPopSongs)

Enter fullscreen mode Exit fullscreen mode

这太棒了,因为我们让事情变得更安全了,代码中引入 bug 的几率也更大了,也意味着测试/调试代码也更容易了。因为我们只需要了解输出,遵循参数,如果输出错误,我们就能确定问题出在函数本身,而不是随机交互。

递归🥞

递归是一种技术,我们可以将问题分成小块来解决问题,这有助于我们在使用交互时避免一些副作用。

function myCount(int i) {
  if(i >= 10) return 0
  else return i + myCount(i+1)
}
myCount(1);
Enter fullscreen mode Exit fullscreen mode

对我来说,递归使代码更具声明性、更易读和更清晰,尽管在许多情况下我更喜欢使用迭代方式。

函数式编程的超级英雄们

除了递归之外,我们还有树函数来帮助我们操作数据,它们是map-filter-reducer。在 JS 中,函数也被视为值,因此我们可以将其作为参数传递给其他函数。

Map,给定一个数据集合,您可以传递一个函数来转换每个项目。

const numbers = [1, 2, 3];
const doubles = numbers.map(num => num * 2) //[2, 4, 6]
Enter fullscreen mode Exit fullscreen mode

过滤器接收数据集合,您可以传递返回集合子集的条件函数。

const numbers = [1, 2, 3];
const isGreaterThanOne = numbers.filter(num => num > 1) //[2, 3]
Enter fullscreen mode Exit fullscreen mode

最后,Reduce,给定一个数据集合,你可以将其简化为单个值。

const numbers = [1, 2, 3];
const mySum = numbers.reduce((accumulator, num) => accumulator + num) //6
Enter fullscreen mode Exit fullscreen mode

结论💃

我刚开始学习函数式编程,这些事情激励着我不断学习,也让我不断查阅各种资源。当然,函数式编程也有弱点,但这不是重点。如果你需要其他资源,我下面会提供一些,尽情享受吧!

图书

Hackernoon - 理解函数式编程
Frisby 教授撰写的《函数式编程基本指南》
Jichao Ouyang 撰写的函数式 JavaScript 迷你书
实用函数 Javascript 在线书籍

会谈

Anjana Vankil - 函数式编程:是什么?为什么?怎么做?我的最爱之一
Anjana Vankil - 函数式 JS 的不可变数据结构
趣味函数系列

文章来源:https://dev.to/fannyvieira/the-beauty-of-functions-programming-32ck
PREV
自以为是的 React:文件夹结构和文件命名
NEXT
每个开发人员都需要了解的 300 多个免费 API 目录