JavaScript Reduce 101
它起什么作用?
示例
简化为一个数字
简化为数组
简化为一个对象
什么时候知道使用 reduce?
JavaScriptreduce()
函数是一个很有用的数组方法。可惜的是,我之前没怎么花时间学习它,因为它看起来太复杂了。其实,它一点也不难!我们只需要把它分解成足够多的小块。还在等什么?快来尝试理解它吧!
它起什么作用?
根据Mozilla 的说法:
reduce() 方法对数组的每个元素执行一个 reducer 函数(由您提供),从而生成单个输出值。
我认为这个描述有点误导,因为当我听到“单一值”时 - 我会想到一个简单的数字/字符串输出,但 reduce 可以轻松返回一个对象或另一个数组。
示例
Reduce 的使用示例数不胜数。我们将介绍基本的 3 个:
- 简化为一个数字
- 简化为数组
- 简化为一个对象。
简化为一个数字
Reduce 最常见的用途是将数组中的所有元素相加。
const arr = [1,2,3,4];
arr.reduce((acc, currentVal) => acc + currentVal);
// returns 10
好的,刚才发生了什么?
Reduce 会遍历数组中的每个元素(除非我们未指定起始值,否则它会使用第一个元素作为起始值)。在每次迭代中,总会有一个累加器和一个当前值。当你阅读示例时,试着思考一下,在每次迭代中,谁是累加器,谁是当前值?
- 在第一次迭代中,acc 为 1,currentVal 为 2。它执行
acc + currentVal
;1 + 2。 - 在第二次迭代中,acc 现在是 3,currentVal 是 3。它执行
acc + currentVal
;3 + 3。 - 在第三次迭代中,acc 现在为 6,currentVal 为 4。它执行
acc + currentVal
;6 + 4。 - 迭代停止,因为我们到达了数组的末尾。Acc 为 10。它返回 acc 的最终值 10。
简化为数组
假设我们有一个数组
const wealthiestPeople = [
{name: "Gates", worth: 105700000000},
{name: "Bezos", worth: 131000000000},
{name: "Buffet", worth: 82500000000},
{name: "Arnault", worth: 76000000000},
{name: "Helu", worth: 75600000000}
]
小伙子,你会用这些钱做什么🤑?总之,我们想映射并过滤所有净资产低于 1000 亿的人的资产,并返回相同的数组。
wealthiestPeople.reduce((acc, currentVal) => {
if(currentVal.worth > 100000000000){
return acc
}
acc.push(currentVal)
return acc
}, [])
// returns [ { name: 'Buffet', worth: 82500000000 },
{ name: 'Arnault', worth: 76000000000 },
{ name: 'Helu', worth: 75600000000 } ]
Reduce 可以同时进行 map 和 filter,是不是很酷?我们来分解一下。
-
如果你注意到,我们在使用 reduce 函数后传递了一个初始值
[]
。和往常一样,我们迭代每个元素。 -
在第一次迭代中,我们的 acc 是
[]
,currentVal 是{name: "Gates", worth: 105700000000}
。它未通过 worth 测试,因此返回 acc,即[]
。 -
在第二次迭代中,我们的 acc 是
[]
。 currentVal 是{name: "Bezos", worth: 131000000000}
。它也未通过 worth 测试。它返回 acc ,即[]
。 -
在第三次迭代中,我们的 acc 是
[]
。currentVal 是{name: "Buffet", worth: 82500000000}
。它通过了值测试。它将 Buffet 对象推送到 acc 中。它返回 acc,即[{name: "Buffet", worth: 82500000000}]
。 -
在第四次迭代中,我们的 acc 是
[{name: "Buffet", worth: 82500000000}]
。 currentVal 是 arnault 对象。它通过了 worth 测试。它将值推{name: "Arnault", worth: 76000000000}
入 acc 。它返回 acc ,也就是[{name: "Buffet", worth: 82500000000}, {name: "Arnault", worth: 76000000000}]
。 -
在第五次迭代中,我们的 acc 是
[{name: "Buffet", worth: 82500000000}, {name: "Arnault", worth: 76000000000}]
。 currentVal 是 Helu 对象。它通过了值测试。它推送了 Helu 对象。它返回 acc,即[ { name: 'Buffet', worth: 82500000000 },{ name: 'Arnault', worth: 76000000000 },{ name: 'Helu', worth: 75600000000 } ]
。
我希望您开始看到由此出现的一种模式!
一位非常棒的读者提到,使用过滤器可以轻松做到这一点:
wealthiestPeople.filter(function(p) {
return p.worth < 1100000000000
})
在这种情况下, reduce.filter()
是一个更好的工具。reduce
更适合用来处理这种情况,比如当我们必须同时使用map 和 filter 时。例如,如果我们不仅需要根据值进行过滤,还需要将金额转换为字符串并添加$
值,则如下所示:
// same reduce cod as above, except
// add this line before push
currentVal.worth = `$${currentVal.worth}.00`
acc.push(currentVal)
// returns
[ { name: 'Buffet', worth: '$82500000000.00' },
{ name: 'Arnault', worth: '$76000000000.00' },
{ name: 'Helu', worth: '$75600000000.00' } ]
另一位超级棒的读者提到,reduce 比 map + filter 组合更有用,因为我们只需要迭代数组一次而不是两次:一次是在 map 过程中,一次是在 filter 过程中。每次执行 map + filter 时,想想如何使用 reduce 来代替!
回到例子——如果你想把他们的财富加在一起:
wealthiestPeople.reduce((acc, currentVal) => {
return acc + currentVal.worth;
}, 0)
简化为一个对象
我们最后一个任务是将其归约成一个对象。给定同一个数组,我们能否将其归约成一个以数组名称为键、以{worth: xxx}
数组名称为值的对象?例如:
{
'Buffet': {worth: xxx},
'Gates': {worth: xxx},
// etc
}
在继续阅读之前,不妨先花5-10分钟——稍微挣扎一下——自己琢磨一下!如果你遇到困难,别担心(我第一次学的时候也遇到过困难),继续读下去!努力才是关键,所以至少尝试一下。
...
wealthiestPeople.reduce((acc, currentVal) => {
acc[currentVal.name] = {worth: currentVal.worth}
return acc
}, {})
什么时候知道使用 reduce?
每当我们输入一个数组时,都是使用 reduce 的好机会。每当完成一个数组操作并需要返回另一个数组、一个对象或一个值时,reduce 都可以帮你搞定。
你们还觉得 reduce 方法在其他时候有用吗?在下面分享!
如果您有任何问题/疑虑,请告诉我。感谢您阅读到这里。祝您编程愉快!
鏂囩珷鏉ユ簮锛�https://dev.to/iggredible/javascript-reduce-101-563g