跟 map/filter 这些数组方法不同,reduce 最大的特点就是给它一个数组,返回的内容可以是任意类型的值。reduce 也被称为万能数组方法,map/filter 能干的,reduce 也能干。
一个最简单的 reduce 的使用情形。
let arr = [
1, 3, 6, 9
]
const result = arr.reduce(
(total, num) => {
console.log(total, num)
return total + num
}
, 0
)
console.log('result', result)
数组 arr 中的四个元素都是 number ,现在要求它们四个的和,就可以用 reduce 方法,reduce 方法要传入两个参数。
第一个参数是一个函数,因为 reduce 方法遵循函数式编程的思路,所以这里作为函数的这个参数,我们姑且叫它 reducer ,必须是一个纯函数,从参数中拿到输入,它负责的就是 return 回一个输出。
reducer 的第一个参数是一个用来存放最终运算结果的变量,有人叫它 accumulator 收集器,这里是 total ,中文意思是总和,reducer 的第二个参数是 num ,这个是迭代过程中拿到的数组的当前元素。
到 reducer 内部,先添加一个打印语句,监控每次迭代过程中 total 和 num 的变化,便于我们理解运行机制。最后, reducer 返回的是 total 加上 num 。reduce 函数,注意这次说的不是 reducer 了,的第二个参数,要传入的是 reducer 的第一个参数的初始值,这里显然应该传入零。所以,我们的推断是,total 的初始值就是这个零,然后下一次迭代,total 的值就是上一次的 total 加上 num ,也就是上一次 reducer 的 return 值。
终端中,执行 node index.js ,可以看到每次 total 和 num 打印的值,印证了之前的推断。
redux 中常用的一种操作,就是把一个对象数组变成一个以数组中各个对象的 id 为属性名,对象本身为属性值的对象。
let products = [
{
id: '123',
name: '苹果'
},
{
id: '345',
name: '橘子'
}
]
const productsById = products.reduce(
(obj, product ) => {
obj[product.id] = product
return obj
},
{}
)
console.log('result', productsById)
给出一个对象数组 products,每个对象代表一个商品,拥有 id 和 name 两个属性。
把最终转换的输出赋值给 productsById 常量,执行 reduce 方法,收集器是 obj ,当前值放到 product 参数中。
进入 reducer 函数内部,让 obj 中的以当前商品的 id 为属性名,对应的属性值为当前商品对象。然后返回 obj 对象。
reduce 函数的第二个参数是一个空对象,这个会作为 obj 的初始值。
命令行中,执行 node index.js 可以看到 productsById 转换成了一个咱们想要的对象了。