高阶函数 JavaScript JavaScript 中的高阶函数

2025-05-24

高阶函数 JavaScript JavaScript 中的高阶函数

介绍

在 JavaScript 中,函数是值(一等公民)。这意味着它们可以赋值给变量或作为值传递。

let random = function(){
    return Math.random()
}

let giveMeRandom = random // assigning random to a variable
Enter fullscreen mode Exit fullscreen mode

仅仅掌握了这一点,我们就可以用这种语言编写函数式编程了。在函数式编程中,我们大量使用高阶函数。

高阶函数?

高阶函数是将其他函数作为参数返回函数作为结果的函数。

接受其他函数作为参数的函数通常被称为回调函数,因为它会被高阶函数回调。这是 JavaScript 中经常使用的概念。

例如,数组上的map函数就是一个高阶函数。map函数接受一个函数作为参数。


const double = n => n * 2

[1, 2, 3, 4].map(double) // [ 2, 4, 6, 8 ]
Enter fullscreen mode Exit fullscreen mode

或者,使用匿名函数:

[1, 2, 3, 4].map(function(n){
    return n * 2
}) // [ 2, 4, 6, 8 ]
Enter fullscreen mode Exit fullscreen mode

map函数是该语言内置的众多高阶函数之一。sort reduce filter forEach该语言内置的高阶函数的其他示例。

高阶函数可以让你编写更简洁、更优雅的代码。让我们看看上面的代码如果没有这种抽象会是什么样子。让我们用一个循环替换map函数:

let array = [1, 2, 3, 4]
let newArray = []

for(let i = 0; n < array.length; i++) {
    newArray[i] = array[i] * 2
}

newArray // [ 2, 4, 6, 8 ]
Enter fullscreen mode Exit fullscreen mode

构图的力量

当我们可以使用高阶函数时,其最大的优势之一就是组合。

我们可以创建一些较小的函数,只处理单一逻辑。然后,我们再使用不同的小函数来组合出更复杂的函数。

这种技术减少了错误并使我们的代码更易于阅读和理解。

通过学习使用高阶函数,您可以开始编写更好的代码。

例子

让我们举个例子。假设我们有一个班级的成绩列表。我们班有 5 个女生,5 个男生,每个人的成绩都在 0 到 20 之间。

var grades = [
    {name: 'John', grade: 8, sex: 'M'},
    {name: 'Sarah', grade: 12, sex: 'F'},
    {name: 'Bob', grade: 16, sex: 'M'},
    {name: 'Johnny', grade: 2, sex: 'M'},
    {name: 'Ethan', grade: 4, sex: 'M'},
    {name: 'Paula', grade: 18, sex: 'F'},
    {name: 'Donald', grade: 5, sex: 'M'},
    {name: 'Jennifer', grade: 13, sex: 'F'},
    {name: 'Courtney', grade: 15, sex: 'F'},
    {name: 'Jane', grade: 9, sex: 'F'}
]
Enter fullscreen mode Exit fullscreen mode

我想知道一些关于此的事情:

  • 这个教室的平均成绩
  • 男生的平均成绩
  • 女生的平均成绩
  • 男孩们中音调最高的
  • 女孩们中最高的音符

我们将尝试使用高阶函数来编写一个简单易读的程序。让我们从编写一些可以协同工作的简单函数开始:

let isBoy = student => student.sex === 'M'

let isGirl = student => student.sex === 'F'

let getBoys = grades => (
    grades.filter(isBoy)
)

let getGirls = grades => (
    grades.filter(isGirl)
)

let average = grades => (
    grades.reduce((acc, curr) => (
        acc + curr.grade
    ), 0) / grades.length
)

let maxGrade = grades => (
    Math.max(...grades.map(student => student.grade))
)

let minGrade = grades => (
    Math.min(...grades.map(student => student.grade))
)

Enter fullscreen mode Exit fullscreen mode

我写了 7 个函数,每个函数都有一项任务,而且只有一项任务。

isBoyisGirl负责检查一个学生是男孩还是女孩。

getBoysgetGirls负责从教室里取出所有的男孩或女孩。

maxGrademinGrade负责获取某些数据中的最高和最低等级。

最后,平均值负责计算一些数据的平均等级。

请注意,average函数还不知道它要处理的数据类型。这就是组合的美妙之处。我们可以在不同的地方复用我们的代码。我可以直接把这个函数和其他函数连接起来。

现在,我们已经有了编写高阶函数所需的一切:


let classroomAverage = average(grades) // 10.2
let boysAverage = average(getBoys(grades)) // 7
let girlsAverage = average(getGirls(grades)) // 13.4
let highestGrade = maxGrade(grades) // 18
let lowestGrade = minGrade(grades) // 2
let highestBoysGrade = maxGrade(getBoys(grades)) // 16
let lowestBoysGrade = minGrade(getBoys(grades)) // 2
let highestGirlsGrade = maxGrade(getGirls(grades)) // 18
let lowestGirlsGrade = minGrade(getGirls(grades)) // 9
Enter fullscreen mode Exit fullscreen mode

注意,外部函数(例如平均值)总是将内部函数的输出作为输入。因此,组合的唯一条件是确保输出和输入匹配。

而且由于每个函数只负责一件事,这使得我们的代码更容易调试和测试。

构图规则!

文章来源:https://dev.to/damcosset/higher-order-functions-in-javascript-4j8b
PREV
尝试通过制作区块链来了解区块链!
NEXT
使用 Puppeteer 从 HTML 生成 PDF 简介 解决方案!已完成