Logo
Section 1 / 2

它们是什么?

函数对象的简要介绍,以及它们将如何与本课程内容相结合。(4分钟阅读)

导入

它们是什么?

函数对象的简要介绍,以及它们将如何与本课程内容相结合。(4分钟阅读)

FP 定义了自己的类型,而函子(functor)是最基本的一种。可以将其理解为一个容器,用于存放任意类型的值,比如字符串、日期、布尔值、数组、对象等。

这个容器必须拥有一个 map 方法,才能被称为函子。

下面是一个简单的例子:

1const Identity = (x) => ({ 2 value: x, 3 map: (fn) => Identity(fn(x)) 4});

函数 Identity 接收一个值并返回一个函子。

1const name = Identity('Bobo'); 2 3console.log(name);

打印 name 会得到如下结构的函子:

1{ value: 'Bobo', map: [Function: map] }

那么,如何改变这个函子内部的值 'Bobo' 呢?

在 JavaScript 中,我们可以直接修改它:

1const name = Identity('Bobo'); 2 3name.value = name.value.toUpperCase(); 4 5console.log(name);

但根据函数式编程的原则,我们应尽量避免这种可变操作。那如果改用 map 呢?

1const name = Identity('Bobo'); 2const newName = name 3 .map(value => value.toUpperCase()); 4 5console.log({ name, newName });

这样,我们没有修改原有的函子,而是创建了一个全新的函子,包含了我们期望的新值!

由于 map 必须返回相同类型的函子,因此我们可以像数组的 map 一样进行链式调用。

1const name = Identity('Bobo'); 2const newName = name 3 .map(value => value.slice(0, 3)) 4 .map(value => `My name is not ${value}!`) 5 .map(value => value.toUpperCase()); 6 7console.log({ name, newName });

这种方式是不可变的,代码更易读,也更易于组合。

当你需要取出值时,只需访问其 .value 属性即可。

总结

  • 函子是你可以对其应用 map 的容器。
  • 函子可以容纳任何类型的值。
  • map 是一种可组合、不可变的方式来改变函子的值。

为什么关心这个?

透镜(Lenses)使用了函子。我们很快就会深入探讨它们。

运用我们所学的知识

Ramda 如何使用它们