初学者很难区分 JavaScript 中的 map、filter 和 reduce 函数的功能。这是可以理解的,因为他们之间有很多不可思议的相似之处。
相似之处
- 这三个都是 JavaScript 中的高阶函数。
- 所有这些都是数组方法/函数。
- 所有这些都以一个数组和一个修改函数作为输入。
- 在少数情况下,这三者都可以互换使用。
尽管有这些共同点,但重要的是要了解它们的特性以及在哪里使用什么。下面给出一个示例,让您直观地理解它们每个人的作用
map([🌽, 🐮, 🐔], cook)
=> [🍿, 🍔, 🍳]
filter([🍿, 🍔, 🍳], isVegetarian)
=> [🍿, 🍳]
reduce([🍿, 🍳], eat)
=> 💩
map
map 接受一个数组和一个函数,并返回一个经过一些修改的数组(与输入数组大小相同)。当我们想要输出与输入数组具有相同数量的元素的修改后的数组时,本质上会使用 map()。
示例
比方说,你得到一个数字数组,你想将数组的原始值增加三倍,即[2,3,4,5]变为[6,9,12,15],同样。
const input = [2,3,4,5];
function triple(x)
{
return x * 3;
}
const output= input.map(triple);
// output = [6,9,12,15]
triple()是一个函数,它接受整数输入x并返回其三元组3*x。在示例的最后一行中,我们在映射中使用了triple,将triple()函数的效果应用于输入数组的每个元素。
map()本质上用作数组的原型函数,它接受另一个函数f作为其参数,并将函数的效果注入f数组的每个元素。
output本质上是一个数组,其元素数量与数组相同,input但值更改为原始元素的三倍。
最后一个例子的另一种写法
也可以将整个函数体写在triple()map 函数的括号内。即整个函数体可以作为参数传递给map()
const input = [2,3,4,5];
const output = input.map(
function triple(x)
{
return x*3;
}
)
这可以进一步简化,因为 -
const output = input.map((x)=>x*3);
return当函数中只有一行代码时,甚至不需要显式地编写关键字。
filter
filter 接受一个数组和一个函数,并返回一个元素数量少于输入数组的过滤数组。
filter() 方法获取数组中的每个元素,并对其应用条件语句。如果此条件返回 true,则将元素推送到输出数组。如果条件返回 false,则不会将元素推送到输出数组。
与 filter() 相关的所有问题都存在于以下一般结构中: 给定一个数组,创建一个包含所有满足特定条件的元素的数组。
示例
问题:给定一个整数数组,创建一个包含所有可被三整除的元素的新数组。
const numbers = [2,3,5,6,9,10,11,12]
const output = numbers.filter(item=> item%3 === 0);
在上面的代码中,filter里面的函数也可以写成
function isDivisiblebyThree(item)
{
return (item%3 === 0)
}
这与
function isDivisiblebyThree(item)
{
if(item%3 === 0)
return true;
else
return false
}
输出 = [3,6,9,12]
Reduce
Reduce 是 JavaScript 中最重要但也很容易被误解的方法。这是因为它不像地图和过滤器那么直观,至少在第一眼看起来不是。
需要考虑的重要一点是,reduce 函数在完成工作后本质上只返回一个对象,这与抛出数组的 map 和 filter 不同。
根据 mdn 网络文档:
该 reduce()方法按顺序对数组的每个元素执行用户提供的“reducer”回调函数,传入前一个元素计算的返回值。在数组的所有元素上运行 reducer 的最终结果是单个值。
假设您有一个数字数组nums,您想要将其加到给定值initialValue(在示例中为 10),这样最后,累加器将是数组的所有值和初始值的总和. 我们先用一个for循环来完成这个任务
let initialValue = 10;
let accumulator = initialValue;
let nums = [1,2,3,4,5];
for(n of nums)
{
initialValue = initialValue + n;
}
上面的代码可以使用reduce函数编写如下
nums.reduce((accumulator,currentValue)=>{
return (accumulator + currentValue);
},initialValue)
reduce 函数会将(accumulator+currentValue)回调函数每次迭代后返回的值存储到累加器本身中。initialValue 是累加器最初开始的值。
在使用 reduce() 方法时有很多语法
// Arrow function
reduce((previousValue, currentValue) => { /* … */ } )
reduce((previousValue, currentValue, currentIndex) => { /* … */ } )
reduce((previousValue, currentValue, currentIndex, array) => { /* … */ } )
reduce((previousValue, currentValue) => { /* … */ } , initialValue)
reduce((previousValue, currentValue, currentIndex) => { /* … */ } , initialValue)
reduce((previousValue, currentValue, currentIndex, array) => { /* … */ }, initialValue)
// Callback function
reduce(callbackFn)
reduce(callbackFn, initialValue)
// Inline callback function
reduce(function(previousValue, currentValue) { /* … */ })
reduce(function(previousValue, currentValue, currentIndex) { /* … */ })
reduce(function(previousValue, currentValue, currentIndex, array) { /* … */ })
reduce(function(previousValue, currentValue) { /* … */ }, initialValue)
reduce(function(previousValue, currentValue, currentIndex) { /* … */ }, initialValue)
reduce(function(previousValue, currentValue, currentIndex, array) { /* … */ }, initialValue)
结论
使用 map、filter 和 reduce 方法或任何新概念的清晰度随着越来越多的实践而来。我建议读者通过实施任何在初读时不完全有意义的东西来学习。