高阶数组函数 forEach、map 和 filter
诸如forEach()
、map()
和之类的数组方法filter()
是一些高阶数组函数,当您必须处理数组中的数据时,它们非常方便。
在本文中,我们将讨论以下高阶函数,并举例说明:
forEach()
map()
filter()
我假设您对高阶函数是什么以及如何使用它们有基本的了解,如果没有,我建议您阅读我之前的文章。
数组.forEach()
forEach()
方法对于对数组中的每个元素执行某些操作非常有用。
forEach()
数组上的方法按升序索引(从 0 开始)对数组中的每个元素执行提供的回调函数。
句法
forEach(callbackFn)
forEach((element, index, array) => { /* ... */ } )
参数
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
由于forEach()
是数组本身的方法,我们可以使用点符号在任何数组上调用它。
在上面的例子中,我们使用箭头函数作为回调函数调用了两次Array.forEach()
高阶函数forEach()
,并在的参数中定义。
假设我们有一个全名数组,你需要将所有全名拆分成firstName
一个lastName
对象,并将它们推送到一个已经包含相同类型数据的数组中。你会怎么做?
const fullNames = ["Adam Benson","Clare Donaldson","Ben Adams","Donald Clarkson"]
下面介绍如何使用forEach()
将包含firstName
和lastName
属性的对象推送到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' }
]
*/
在上面的例子中,我们在回调函数中创建了一个空对象obj
来存储属性。然后,我们将数组的当前元素按空格分割,立即解构,并将其存储到属性firstName
和lastName
对象中obj
。最后,我们将对象推送到names
数组中。
数组.map()
Array.map()
当您必须通过对现有数组执行某个函数来创建新数组时,此方法非常方便。
Array.map()
数组上的方法返回一个新数组,该数组中填充了按升序索引(从 0 开始)对数组中每个元素调用的回调函数的返回值。
句法
map(callbackFn)
map((element, index, array) => { /* ... */ } )
// returns a new array populated with results of callbackFn
参数
callbackFn
对 的每个元素执行的函数arr
。每次callbackFn
执行时,返回值都会添加到newArray
。
它接受一到三个参数:
element
:数组中正在处理的当前元素。index
(可选element
):数组中的索引。 array
(可选map()
):被调用的数组。
返回值
该map()
方法返回一个新数组,其中每个元素都是回调函数的结果。
示例
假设我们得到了以下数组,并被要求生成另一个由所有相应元素的平方组成的数组。
const numbs = [5, 9, 10, 1] // our boring array of numbers
最简单的方式是使用该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 ]
map()
这太简单了吧?我们需要做的就是在数组上调用该方法numbs
,并返回当前元素的平方来实现我们的逻辑。由于该map()
方法本身返回一个新数组,我们将其存储在变量中sqaures
。
现在我们来看另一个例子,我们将转换一个包含firstName
和lastName
属性的对象数组(这些对象是我们在 中得到的输出)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' ]
上面,您在查看示例时首先会注意到的是我们没有lastName
我的名字的属性,我们的逻辑也必须处理这个问题。
在我们的方法的回调中,map()
我们使用模板文字来连接firstName
和lastName
(如果有的话:使用可选链接)以形成。并从回调中full_name
返回修剪。full_name
数组.filter()
顾名思义,该方法用于筛选出满足一定条件的数组。
Array.filter()
数组上的方法返回一个新数组,其中仅包含通过回调函数中的测试条件的元素。
句法
filter(callbackFn)
filter((element, index, array) => { /* ... */ })
// returns a new array with elements that satisfy the callback condition.
参数
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 :)
让我们针对我们无聊的数组提出几个问题filter
。
Q1 .从numbs
const odd = numbs.filter(n => n % 2 !== 0)
console.log(odd)
// [ 5, 9, 1, 3]
在回调中,我们仅对数组中的奇数返回 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 ]
这isPrime
是我们的回调filter
方法,该方法在每个元素时都会被调用numbs
,并作为我们的条件来过滤掉素数。
map()
下面是和方法的复合示例filter()
。我将创建一个数组,其中包含我的 GitHub Repos 的名称,这些 Repos 主要使用SCSS编写。
该示例是一个异步函数 IIFE
(立即调用函数表达式) ,一旦定义就会被调用。在我们的异步函数中,我使用 GitHub 的 REST API 以 JSON 格式获取与我的 GitHub 存储库相关的数据。
该 API 返回一个对象数组,其中包含按字母顺序列出的我的公共 GitHub 仓库的信息。您可以通过访问以下 URL 查看 API 的响应:
- 最多 30 个 repos:https://api.github.com/users/AnilSeervi/repos
- 所有存储库:https://api.github.com/users/anilseervi/repos? per_page=100
该 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']
})()
从URL获取的响应(JSON 格式)存储在 中res
,然后转换为存储在 中的 JavaScript 对象data
。
注意:存储库的名称和数量可能会根据您阅读本文的时间而发生变化。
现在我们有一个包含所有 repos 对象的数组,我们需要根据language
属性对其进行过滤。语言属性为 的对象SCSS
将被过滤为filterJSRepos
常量。
过滤 Repos 后,我们现在可以使用并获取已name
过滤 Repos 的属性,瞧,这就是包含我的 repos 名称的数组,其中主要包含SCSS。map()
我希望本文能帮助您理解高阶数组函数(forEach()
,,)map()
。filter()
感谢您的阅读,让我们联系起来!
感谢您阅读我的博客。欢迎在这里提问和留言,我们也可以一起在Twitter 上交流!
文章来源:https://dev.to/anilseervi/higher-order-array-function-foreach-map-and-filter-f64