理解 JavaScript 中的高阶函数

  1. 云栖社区>
  2. 博客>
  3. 正文

理解 JavaScript 中的高阶函数

初商 2019-08-06 21:39:34 浏览570

image.png

原文作者:Sukhjinder Arora

译者:UC 国际研发 Jothy


本文将让大家了解什么是高阶函数以及如何在 JavaScript 中使用它们。

如果你正在学习 JavaScript,那么你应该见过高阶函数这个术语。 它虽然听起来很复杂,但其实并不难。

使 JavaScript 适合函数式编程的原因是它接受高阶函数。

高阶函数在 JavaScript 中广泛使用。 如果你已经用 JavaScript 编程了一段时间,你可能已经在不知不觉中用过它们了。

要完全理解这个概念,首先必须了解函数式编程以及一等函数(First-Class Functions)的概念。

什么是函数式编程

在大多数简单的术语中,函数式是一种编程形式,你可以将函数作为参数传递给其他函数,并将它们作为值返回。 在函数式编程中,我们以函数的形式思考和编程。

JavaScript,Haskell,Clojure,Scala 和 Erlang 是部分实现了函数式编程的语言。

一等函数

如果你在学习 JavaScript,你可能听说过 JavaScript 将函数视为一等公民。 那是因为在 JavaScript 及其他函数式编程语言中,函数是对象。

在 JavaScript 中,函数是一种特殊类型的对象。 它们是 Function objects。例如:

image.png

为了证明 JavaScript 中函数是对象,我们可以这样做:

image.png

注意 - 虽然这在 JavaScript 中完全有效,但这被认为是 harmful 的做法。 你不应该向函数对象添加随机属性,如果不得不这样做,请使用对象。

在 JavaScript 中,你对其他类型(如对象,字符串或数字)执行的所有操作都可以对函数执行。 你可以将它们作为参数传递给其他函数(回调函数),将它们分配给变量并传递它们等等。这就是 JavaScript 中的函数被称为一等函数的原因。

将函数赋值给变量

我们可以在 JavaScript 中将函数赋值给变量。 例如:
image.png

我们也可以传递它们。 例如:

image.png

将函数作为参数传递

我们可以将函数作为参数传递给其他函数。 例如:

image.png

既然我们已经知道一等函数是什么了,那就让我们开始学习 JavaScript 中的高阶函数叭~

高阶函数

高阶函数是对其他函数进行操作的函数,操作可以是将它们作为参数,或者是返回它们。 简单来说,高阶函数是一个接收函数作为参数或将函数作为输出返回的函数。

例如,Array.prototype.map,Array.prototype.filter 和 Array.prototype.reduce 是语言中内置的一些高阶函数。

动手实践高阶函数

让我们看看一些内置高阶函数的例子,看看它与不使用高阶函数的方案对比如何。

Array.prototype.map

map() 方法通过调用对输入数组中每个元素调用回调函数来创建一个新数组。

map() 方法将获取回调函数中的每个返回值,并使用这些值创建一个新数组。

传递给 map() 方法的回调函数接受 3 个参数:element,index 和 array。

我们来看一些例子:

例 1:
假设我们有一个数字数组,我们想要创建一个新数组,其中包含第一个数组中每个值的两倍。 让我们看看如何使用和不使用高阶函数来解决问题。

不使用高阶函数

image.png

使用高阶函数 map

image.png

使用箭头函数语法将更简短:

image.png

例 2:

假设我们有一个包含不同人的出生年份的数组,我们想要创建一个包含其年龄的数组。 例如:

不使用高阶函数

image.png

使用高阶函数

image.png

Array.prototype.filter

filter() 方法会创建一个新数组,其中包含所有通过回调函数测试的元素。 传递给 filter() 方法的回调函数接受3个参数:element,index 和 array。

让我们看看一些例子:

例 1:
假设我们有一个包含名称和年龄属性的对象数组。 我们想要创建一个只包含成年人(年龄大于或等于18)的数组。

不使用高阶函数

image.png

使用高阶函数

image.png

Array.prototype.reduce

reduce 方法对调用数组的每个元素执行回调函数,最后生成一个单一的值并返回。 reduce 方法接受两个参数:1)reducer 函数(回调),2)一个可选的 initialValue。

reducer 函数(回调)接受四个参数:accumulator,currentValue,currentIndex,sourceArray。

如果提供了 initialValue,则累加器将等于 initialValue,currentValue 将等于数组中的第一个元素。

如果没有提供 initialValue,则累加器将等于数组中的第一个元素,currentValue 将等于数组中的第二个元素。

例 1:
假设我们要对一个数字数组的求和:

使用高阶函数 reduce

image.png

每次对数组中的某个值调用 reducer 函数,累加器都会保留上一次 reducer 函数操作返回的结果,并将 currentValue 设置为数组的当前值。 最后把结果存储在 sum 变量中。

我们还可以为它提供初始值:

image.png

不使用高阶函数

image.png

可以看到使用高阶函数使我们的代码更清晰简洁。

创建我们自己的高阶函数

到目前为止,我们看到了语言中内置的各种高阶函数。 现在让我们创建自己的高阶函数。

我们假设 JavaScript 没有原生的 map 方法。 我们可以自己构建它,从而创建我们自己的高阶函数。

假设我们有一个字符串数组,我们希望把它转换为整数数组,其中每个元素代表原始数组中字符串的长度。

image.png

在上面的例子中,我们创建了一个高阶函数 mapForEach ,它接受一个数组和一个回调函数 fn。 它循环遍历传入的数组,并在每次迭代时在 newArray.push 方法调用回调函数 fn 。

回调函数 fn 接收数组的当前元素并返回该元素的长度,该元素存储在 newArray 中。 for 循环完成后,newArray 被返回并赋值给 lenArray。

结论

我们已经了解了高阶函数和一些内置的高阶函数,还学习了如何创建自己的高阶函数。

简而言之,高阶函数是一个可以接收函数作为参数,甚至返回一个函数的函数。 它就像常规函数一样,只是多了接收和返回其他函数的附加能力,即参数和输出。

以上。如果你发现这篇文章有用,请为我点赞~

英文原文:
https://blog.bitsrc.io/understanding-higher-order-functions-in-javascript-75461803bad