高阶数组函数 forEach、map 和 filter

2025-06-04

高阶数组函数 forEach、map 和 filter

诸如forEach()map()和之类的数组方法filter()是一些高阶数组函数,当您必须处理数组中的数据时,它们非常方便。

在本文中,我们将讨论以下高阶函数,并举例说明:

  • forEach()
  • map()
  • filter()

我假设您对高阶函数是什么以及如何使用它们有基本的了解,如果没有,我建议您阅读我之前的文章。


数组.forEach()

forEach()方法对于对数组中的每个元素执行某些操作非常有用。

forEach()数组上的方法按升序索引(从 0 开始)对数组中的每个元素执行提供的回调函数

句法

forEach(callbackFn)
forEach((element, index, array) => { /* ... */ } )
Enter fullscreen mode Exit fullscreen mode

参数

callbackFn
在每个元素上执行的函数。它接受一到三个参数:

element:数组中正在处理的当前元素。
index可选element):数组中的索引。
array可选forEach()):被调用的数组。

forEach()方法不返回任何内容:undefined

如果您查看此方法中的回调函数的签名,它看起来类似于forEach()我在上一篇高阶函数文章中创建的函数。


示例

现在让我们使用该方法重新创建相同的示例Array.forEach()

const numbs = [5, 9, 10, 1]                 // Array of numbers

numbs.forEach((n, i, arr) => {              // n => element, i => index, arr => array(numbs)
 arr[i] = n + 2                             // add 2 to current element
})

numbs.forEach((n) => console.log(n))        // logs all element one-by-one
// 7
// 11
// 12
// 3
Enter fullscreen mode Exit fullscreen mode

由于forEach()是数组本身的方法,我们可以使用点符号在任何数组上调用它。

在上面的例子中,我们使用箭头函数作为回调函数调用了两次Array.forEach() 高阶函数forEach(),并在的参数中定义。


假设我们有一个全名数组,你需要将所有全名拆分成firstName一个lastName对象,并将它们推送到一个已经包含相同类型数据的数组中。你会怎么做?

const fullNames = ["Adam Benson","Clare Donaldson","Ben Adams","Donald Clarkson"]
Enter fullscreen mode Exit fullscreen mode

下面介绍如何使用forEach()将包含firstNamelastName属性的对象推送到names数组。

const names = [ { firstName: 'Anil', lastName: 'Seervi' } ]

fullNames.forEach((n) => {
 const obj = {}                             // empty object for initialization
 [obj.firstName, obj.lastName] = n.split` ` // split at spaces and destructure initialize
 names.push(obj)                            // push the object to names array
})

console.log(names)
/*
[
  { firstName: 'Anil', lastName: 'Seervi' }
  { firstName: 'Adam', lastName: 'Benson' },
  { firstName: 'Clare', lastName: 'Donaldson' },
  { firstName: 'Ben', lastName: 'Adams' },
  { firstName: 'Donald', lastName: 'Clarkson' }
]
*/
Enter fullscreen mode Exit fullscreen mode

在上面的例子中,我们在回调函数中创建了一个空对象obj来存储属性。然后,我们将数组的当前元素按空格分割,立即解构,并将其存储到属性firstNamelastName对象中obj。最后,我们将对象推送到names数组中。


数组.map()

Array.map()当您必须通过对现有数组执行某个函数来创建新数组时,此方法非常方便。

Array.map()数组上的方法返回一个新数组,该数组中填充了按升序索引(从 0 开始)对数组中每个元素调用的回调函数的返回

句法

map(callbackFn)
map((element, index, array) => { /* ... */ } )
// returns a new array populated with results of callbackFn
Enter fullscreen mode Exit fullscreen mode

参数

callbackFn
对 的每个元素执行的函数arr。每次callbackFn执行时,返回值都会添加到newArray
它接受一到三个参数:

element:数组中正在处理的当前元素。
index可选element):数组中的索引。
array可选map()):被调用的数组。

返回值

map()方法返回一个新数组,其中每个元素都是回调函数的结果。


示例

假设我们得到了以下数组,并被要求生成另一个由所有相应元素的平方组成的数组。

const numbs = [5, 9, 10, 1]     // our boring array of numbers
Enter fullscreen mode Exit fullscreen mode

最简单的方式是使用该Array.map()方法:

const squares = numbs.map(n => n ** 2)
// Yes, its easy as that!!

console.log(numbs)
// [ 5, 9, 10, 1 ]
console.log(sqaures)
// [ 25, 81, 100, 1 ]
Enter fullscreen mode Exit fullscreen mode

map()这太简单了吧?我们需要做的就是在数组上调用该方法numbs,并返回当前元素的平方来实现我们的逻辑。由于该map()方法本身返回一个新数组,我们将其存储在变量中sqaures


现在我们来看另一个例子,我们将转换一个包含firstNamelastName属性的对象数组(这些对象是我们在 中得到的输出)forEach(),并创建另一个仅包含全名的数组。这和我们在forEach()例子中所做的有点相反。

// array of objects with firstName and lastName
const names = [
 { firstName: 'Anil' },
 { firstName: 'Adam', lastName: 'Benson' },
 { firstName: 'Clare', lastName: 'Donaldson' },
 { firstName: 'Ben', lastName: 'Adams' },
 { firstName: 'Donald', lastName: 'Clarkson' },
]

// create a new Array of fullNames using names Array
const fullNames = names.map((name) => {
 const full_name = `${name.firstName} ${name?.lastName || ""}`
 return full_name.trimEnd()
})

console.log(fullNames)
// [ 'Anil', 'Adam Benson', 'Clare Donaldson', 'Ben Adams', 'Donald Clarkson' ]
Enter fullscreen mode Exit fullscreen mode

上面,您在查看示例时首先会注意到的是我们没有lastName我的名字的属性,我们的逻辑也必须处理这个问题。

在我们的方法的回调中,map()我们使用模板文字来连接firstNamelastName(如果有的话:使用可选链接)以形成。并从回调中full_name返回修剪。full_name

数组.filter()

顾名思义,该方法用于筛选出满足一定条件的数组。

Array.filter()数组上的方法返回一个新数组,其中仅包含通过回调函数中的测试条件的元素

句法

filter(callbackFn)
filter((element, index, array) => { /* ... */ })
// returns a new array with elements that satisfy the callback condition.
Enter fullscreen mode Exit fullscreen mode

参数

callbackFn
函数是用于对 的每个元素执行的谓词arr。每次callbackFn调用 时,只有element强制转换为 的true才会添加到新数组中。
它接受一到三个参数:

element:数组中正在处理的当前元素。
index可选element):数组中的索引。
array可选filter()):被调用的数组。

返回值

filter()方法返回一个新数组,其中仅包含满足测试条件的元素callbackFn

示例

为了更容易理解,我采用相同的旧numbs数组来处理。

const numbs = [5, 9, 10, 1, 6, 3]       // hey, I'm bigger this time :)
Enter fullscreen mode Exit fullscreen mode

让我们针对我们无聊的数组提出几个问题filter

Q1 .numbs

const odd = numbs.filter(n => n % 2 !== 0)

console.log(odd)
// [ 5, 9, 1, 3]
Enter fullscreen mode Exit fullscreen mode

在回调中,我们仅对数组中的奇数返回 true ,从而返回numbs数组中的所有奇数。

Q2 .numbs

function isPrime(numb) {
 for (let i = 2, s = Math.sqrt(numb); i <= s; i++)
 if (numb % i === 0) return !1
 return numb > 1
}

console.log(numbs.filter(isPrime))
// [ 5, 3 ]
Enter fullscreen mode Exit fullscreen mode

isPrime是我们的回调filter方法,该方法在每个元素时都会被调用numbs,并作为我们的条件来过滤掉素


map()下面是和方法的复合示例filter()。我将创建一个数组,其中包含我的 GitHub Repos 的名称,这些 Repos 主要使用SCSS编写。

该示例是一个异步函数 IIFE(立即调用函数表达式) ,一旦定义就会被调用。在我们的异步函数中,我使用 GitHub 的 REST API 以 JSON 格式获取与我的 GitHub 存储库相关的数据。

该 API 返回一个对象数组,其中包含按字母顺序列出的我的公共 GitHub 仓库的信息。您可以通过访问以下 URL 查看 API 的响应:

该 API 最多仅返回 30 个存储库,且不带任何查询参数。

(async function jsRepos() {
 const res = await fetch("https://api.github.com/users/AnilSeervi/repos?per_page=100")    // fetch the JSON from API
 const data = await res.json()                                      // parse JSON to JavaScript Object

 const filterJSRepos = data.filter(i => i.language === "SCSS")      // filter the Repos based on language
 const repoNames = filterReposData.map(i => i.name)                 // Create an array of filtered Repo names

 console.log(repoNames)
 // ['DevFolio', 'mdn-minimalist', 'ts-portfolio']
})()
Enter fullscreen mode Exit fullscreen mode

从URL获取的响应(JSON 格式)存储在 中res,然后转换为存储在 中的 JavaScript 对象data

注意:存储库的名称和数量可能会根据您阅读本文的时间而发生变化。

现在我们有一个包含所有 repos 对象的数组,我们需要根据language属性对其进行过滤。语言属性为 的对象SCSS将被过滤为filterJSRepos常量。

过滤 Repos 后,我们现在可以使用并获取已name过滤 Repos 的属性,,这就是包含我的 repos 名称的数组,其中主要包含SCSSmap()


我希望本文能帮助您理解高阶数组函数forEach(),,map()filter()

感谢您的阅读,让我们联系起来!

感谢您阅读我的博客。欢迎在这里提问和留言,我们也可以一起在Twitter 上交流!

文章来源:https://dev.to/anilseervi/higher-order-array-function-foreach-map-and-filter-f64
PREV
ECMAScript 2021 最新更新
NEXT
使用 Mergify 像专业人士一样合并拉取请求