ES6 高阶函数

2025-06-07

ES6 高阶函数

介绍

在本文中,我们将首先了解什么是高阶函数,然后查看一些流行的高阶函数的代码示例,例如 forEach、map、filter、reduce 等。

什么是高阶函数?

在我们转向高阶函数之前,首先了解什么是一等公民是很重要的。

一等公民

在 JavaScript 中,函数被视为“一等公民”。因为在 JavaScript 中,函数本质上是一个对象。

让我们举一个简单的例子来更好地解释这一点。下面的代码是一个简单函数的示例。

//A simple function
function sayHello() {
    console.log('Hello');
}

//Invoke the function
sayHello(); //output -> Hello
Enter fullscreen mode Exit fullscreen mode

当我们说函数是对象时,我们可以为函数分配类似于对象的属性,如下所示。

//Since the function is essentially an object, you can add properties to it
sayHello.greet = 'Namaste';

console.log(sayHello.greet); // Output -> Namaste
Enter fullscreen mode Exit fullscreen mode

注意:虽然我们可以为函数赋值属性,但这通常被认为是一种不好的做法。如果必须添加属性,请确保使用对象。

您还可以将变量分配给函数,如下面的代码示例所示:

//A simple function
const sayHello = function() {
    console.log('Hello');
}

//Invoke the function
sayHello(); //output -> Hello
Enter fullscreen mode Exit fullscreen mode

上述示例是“一流”功能的示例。

高阶函数

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

希望下面的代码示例能够使上述解释更加清晰。

//Function Sum of two arguments a & b
const sum = function (a, b) {
  return a + b;
};

//Higher order function - takes 'func' as an argument & returns a 'func' for execution
const higherOrderFunction = (func) => (a, b) => {
  return func(a, b);
};
const sumFor = higherOrderFunction(sum);

console.log(sumFor);

/**
 *  The Output of sumFor (HigherOrderFunction) is
 *  (a, b) => {
 *     return func(a, b);
 *  }
 * 
 */

console.log(sumFor(2, 3)); //Output -> 5
Enter fullscreen mode Exit fullscreen mode

注意事项:

  • 函数“higherOrderFunction”接受函数“func”作为参数。
  • 作为参数传入的函数“func”称为回调。

Array.prototype.forEach、Array.prototype.map、Array.prototype.filter 是 ES5 引入的几个高阶函数的例子。

让我们深入了解其实际功能。

数组.forEach

forEach 函数在 ES5 中以 Array.prototype.forEach 的形式引入,而在 ES6 中,它被简单地引用为 Array.forEach。

语法:Array.forEach(callback(currentValue, currentIndex,array));

回调函数接收三个参数:

  • 当前元素值 - 必填
  • 当前元素索引-可选
  • 正在遍历的数组。

让我们看一个代码示例:

//An array of Marvel Movies with the title & year of release
const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
  },
  {
    title: "The Avengers",
    year: 2012,
  },
  {
    title: "Doctor Strange",
    year: 2016,
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
  },
  {
    title: "Avengers: End Game",
    year: 2019,
  },
];

//forEach loops through each movie & prints the name of the title & year it was released on the console
//The anonymous function accepts 'movie' as an argument which matches with the current element
marvelMovies.forEach((movie) => {
  console.log(`The title of the movie is $${movie.title}`);
  console.log(`${movie.year} is the year the movie was released.`);
});

/*
Output
---------
The title of the movie is $Iron Man
2008 is the year the movie was released.
The title of the movie is $The Avengers
2012 is the year the movie was released.
The title of the movie is $Doctor Strange
2016 is the year the movie was released.
The title of the movie is $Avengers: Infinity War
2018 is the year the movie was released.
The title of the movie is $Avengers: End Game
2019 is the year the movie was released.
---------
*/
Enter fullscreen mode Exit fullscreen mode

注意事项:

  • 回调函数是一个匿名函数。它与箭头函数一起使用。如果你想复习一下箭头函数,可以阅读这里
  • 我使用了“movie”来引用作为参数传入的当前元素。实际上,你可以使用任何名称来引用当前元素的变量。
  • forEach 循环遍历“marvelMovies”数组并在控制台上显示标题和发行年份。

数组.map

ES5 中引入了 map 函数,形式为 Array.prototype.map,而 ES6 中则简单地将其称为 Array.map。

语法:Array.map(callback(currentValue, currentIndex, array));

回调函数接收三个参数:

  • 当前元素值 - 必填
  • 当前元素索引-可选
  • 正在遍历的数组。

这里要注意的重要一点是,“map”函数返回一个“新”数组,其中回调函数的结果以相同的顺序应用于原始数组的每个元素。

让我们采用相同的 marvelMovies 数组并使用 map 函数仅对标题为“复仇者联盟”的电影进行评级。

//An array of Marvel Movies with the title & year of release
const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
  },
  {
    title: "The Avengers",
    year: 2012,
  },
  {
    title: "Doctor Strange",
    year: 2016,
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
  },
  {
    title: "Avengers: End Game",
    year: 2019,
  },
];

//map Function
//marvelMovies.map function will return a new array that'll be assigned to newMarvelMovies
const newMarvelMovies = marvelMovies.map((marvelMovie) => {

        //Check if the title contains 'Avengers'
    if(marvelMovie.title.includes('Avengers')) {
                //Add the 'rating' atrribute to the current element
        marvelMovie['rating'] = 5;
    }
        //the element will be returned as a part of the anonymous function
        //the element will be added as a part of the new array being returned from the map function
    return marvelMovie;
});

//Display the value of the new Array 'newMarvelMovies'
console.log(newMarvelMovies);

/*
Output ->
0: {title: "Iron Man", year: 2008}
1: {title: "The Avengers", year: 2012, rating: 5}
2: {title: "Doctor Strange", year: 2016}
3: {title: "Avengers: Infinity War", year: 2018, rating: 5}
4: {title: "Avengers: End Game", year: 2019, rating: 5}
*/
Enter fullscreen mode Exit fullscreen mode

注意事项:

  • “map”函数返回一个“新”数组。
  • 在这个例子中,我使用“marvelMovie”名称作为当前元素,只是为了证明任何名称都可以用于引用当前元素。
  • “map”函数的主要用例是编辑或操作数组的元素。

数组.过滤器

过滤器函数在 ES5 中以 Array.prototype.filter 的形式引入,而在 ES6 中,它被简单地引用为 Array.filter。

语法:Array.filter(callback(currentValue, currentIndex, array));

回调函数接收三个参数:

  • 当前元素值 - 必填
  • 当前元素索引-可选
  • 正在遍历的数组。

过滤函数创建一个新数组,其中包含通过回调函数中指定的条件检查的所有元素。

让我们看看下面的代码示例:

//An array of Marvel Movies with the title & year of release
const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
  },
  {
    title: "The Avengers",
    year: 2012,
  },
  {
    title: "Doctor Strange",
    year: 2016,
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
  },
  {
    title: "Avengers: End Game",
    year: 2019,
  },
];

//filter Function
//filteredMarvelMovies is a new array
//marvelMovies.filter function will return only the elements who's title does not contain 'Avengers'
const filteredMarvelMovies = marvelMovies.filter((marvelMovie) => {
    return !marvelMovie.title.includes('Avengers');
});

//Display the value of the new Array 'filteredMarvelMovies'
console.log(filteredMarvelMovies);

/*
Output ->
0: {title: "Iron Man", year: 2008}
1: {title: "Doctor Strange", year: 2016}
*/
Enter fullscreen mode Exit fullscreen mode

注意事项:

  • “filter”函数返回一个“新”数组。
  • “过滤”函数的主要用例是提取符合特定条件的数组元素的特定子集。

数组.some

ES5 中引入了“some”函数,即 Array.prototype.filter,而在 ES6 中,它被简单地称为 Array.some。

语法:Array.some(callback(currentValue, currentIndex, array));

回调函数接收三个参数:

  • 当前元素值 - 必填
  • 当前元素索引-可选
  • 正在遍历的数组。

some 函数测试数组中是否至少有一个元素满足回调函数中指定的测试条件。它返回一个布尔值。

让我们看看下面的代码示例:

//An array of Marvel Movies with the title & year of release
const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
  },
  {
    title: "The Avengers",
    year: 2012,
  },
  {
    title: "Doctor Strange",
    year: 2016,
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
  },
  {
    title: "Avengers: End Game",
    year: 2019,
  },
];

//some function
//Checks & return a true if any one element title of the marvelMovies array 
//matches with the string 'Thor'
const checkTitle = marvelMovies.some(movie => {
    return movie.title === 'Thor'; 
});

//Display the boolean value returned from the 'some' function
console.log(checkTitle); //output -> false
Enter fullscreen mode Exit fullscreen mode

我相信上面的代码和注释是不言自明的。基本上,“some”函数检查数组中是否有任何一个值符合条件(标题匹配“Thor”),并返回值“false”,因为 marvelMovies 数组中没有匹配的值。

数组.every

ES5 中以 Array.prototype.every 的形式引入了“every”函数,而在 ES6 中,它被简单地引用为 Array.every。

语法:Array.every(callback(currentValue, currentIndex, array));

回调函数接收三个参数:

  • 当前元素值 - 必填
  • 当前元素索引-可选
  • 正在遍历的数组。

every 函数测试数组中的所有元素是否都满足回调函数中指定的条件。它返回一个布尔值。

我们来看下面的代码示例:

//An array of Marvel Movies with the title, year of release & rating
const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
    rating: 5
  },
  {
    title: "The Avengers",
    year: 2012,
    rating: 5
  },
  {
    title: "Doctor Strange",
    year: 2016,
    rating: 4
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
    rating: 5
  },
  {
    title: "Avengers: End Game",
    year: 2019,
    rating: 5
  },
];

//every function
//Checks & returns a 'true' if all of elements in the marvelMovies array have a rating above 3
const checkRating = marvelMovies.every(movie => {
    return movie.rating > 3; 
});

//Display the boolean value returned from the 'every' function
console.log(checkRating); //output -> true
Enter fullscreen mode Exit fullscreen mode

Array.find 和 Array.findIndex

find 和 findIndex 在 ES5 中以 Array.prototype.find 和 Array.prototype.findIndex 的形式引入。在 ES6 中,它们可以以 Array.find 和 Array.findIndex 的形式使用。

Array.find 函数根据回调函数中指定的条件返回第一个匹配的元素。

Array.findIndex 函数根据回调函数中指定的条件返回第一个匹配元素的索引。

下面的代码示例给出了如何使用 find 和 findIndex 函数的简单示例。

//An array of Marvel Movies with the title, year of release & rating
const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
    rating: 4
  },
  {
    title: "The Avengers",
    year: 2012,
    rating: 3
  },
  {
    title: "Doctor Strange",
    year: 2016,
    rating: 4
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
    rating: 5
  },
  {
    title: "Avengers: End Game",
    year: 2019,
    rating: 5
  },
];

//find function
//Checks & returns the first element that matches with the condition 'rating' greater than 5
const found = marvelMovies.find(movie => {
    return movie.rating === 4; 
});

//Display the value of 'found' in the Console
console.log(found); 

//output -> {title: "Avengers: Infinity War", year: 2018, rating: 5}
//Even though the movie 'Avengers: End Game' also contains the rating 5,
//the first matching element is returned

--------------------------------------------------------------------------

//findIndex function
//Checks & returns the first element that matches with the condition 'rating' greater than 5
const foundIndex = marvelMovies.findIndex(movie => {
    return movie.rating === 4; 
});

//Display the value of 'foundIndex' in the Console
console.log(foundIndex); //Output -> 3 (Array index starts from 0)
Enter fullscreen mode Exit fullscreen mode

数组.reduce

'reduce' 函数在 ES5 中以 Array.prototype.reduce 的形式引入。在 ES6 中,它被简化为 Array.reduce。

语法:Array.reduce(callback(accumulator, currentValue, currentIndex, array));

回调函数接收四个参数:

  • 累加器 - 强制
  • 当前元素值 - 必填
  • 当前元素索引-可选
  • 正在遍历的数组。

Reducer 函数对数组的每个元素执行指定的回调函数,最终返回单个值。

简单来说,通过每次迭代,回调函数返回的值被赋给“累加器”,并最终成为最终的单一结果值。

Reduce 函数是最容易被理解的函数。因此,我将先举一个没有使用 Reducer 的例子,然后再使用 Reducer 来解释代码流程。

//The marvelMovies array contains the title & profit each movie has made
const marvelMovies = [
    {
      title: "Iron Man",
      profit: 100000
    },
    {
      title: "The Avengers",
      profit: 200000
    },
    {
      title: "Doctor Strange",
      profit: 200000
    },
];    

//Initialize the totalProfit variable
let totalProfit = 0;

//Use forEach function to loop through the iteration & add the profit of each movie
//to the totalProfit variable
marvelMovies.forEach(movie => {
    totalProfit += movie.profit;
});

//Display the value of totalProfit on console
console.log(totalProfit);
Enter fullscreen mode Exit fullscreen mode

让我们看看如何使用 reduce 函数简化上述代码。

//The marvelMovies array contains the title & profit each movie has made
const marvelMovies = [
    {
      title: "Iron Man",
      profit: 100000
    },
    {
      title: "The Avengers",
      profit: 200000
    },
    {
      title: "Doctor Strange",
      profit: 200000
    },
];

//Use reduce function to loop through the iteration & add the movie's profit
//to the accumulator & return it to the 'totalProfit' variable
const totalProfit = marvelMovies.reduce((accumulator, movie) => {
    return accumulator + movie.profit;
}, 0);

//Display the value of totalProfit on console
console.log(totalProfit);
Enter fullscreen mode Exit fullscreen mode

注意事项:

  • “reduce”函数采用“accumulator”变量,该变量保存每次迭代后的返回值。
  • 在这个例子中,电影的利润被添加到“累加器”中,就像上一个例子中“总计”所做的那样。
  • 减少函数的主要用例是当数组中的任何计算需要产生奇异值时。

结论

总而言之,我们首先了解什么是高阶函数,然后查看了一些函数的代码示例,例如 forEach、map、filter、reduce、same 和 every。

要记住的重要一点是,函数 map 和 filter 都返回“新”数组。

map 函数主要用于根据条件操作数组元素的值,而 filter 函数通常用于根据条件从数组中筛选出少量元素。它们在实际应用中非常常见,尤其是在 React 框架中。

希望你喜欢这篇文章。别忘了在 Twitter 上关注我@skaytech。

如果您喜欢这个,您可能还会喜欢:

文章来源:https://dev.to/skaytech/es6-higher-order-functions-495e
PREV
理解提升
NEXT
实用指南助您保持井然有序、高效高效 简介 长期目标和短期目标 SMART 追踪目标!如何操作? 结论