JavaScript 中 reduce() 函数

Posted by cl9000 on May 30, 2020

好的设计能够促使观看者希望了解更多。——<亚历山大·伊斯里>

Array.prototype.reduce()

reduce() 方法对数组中每个元素执行一个由您提供的 reducer 函数(升序执行),将其结果汇总为单个返回值。

1
2
3
4
5
6
7
8
9
10
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15

reducer 函数接收4个参数:

  • 累加器(acc)(累计器)
  • Current Value (cur) (当前值)
  • 当前索引 (idx) (当前索引)
  • 源数组(src)(源数组)
    你的 减速器 函数的返回值分配给累积器,该返回值在数组的每个迭代中被计算出来,并最终成为最终的单个值。

语法

1
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

普通用法 (累加,关联)

1
2
3
4
5
6
7
8
9
10
// 当前的购物清单
var items = [{price: 10}, {price: 120}, {price: 1000}];

// reducer函数
var reducer = function add(sumSoFar, nextPrice) { return sumSoFar + nextPrice.price; };

// 开始运行
var total = items.reduce(reducer, 0);

console.log(total); // 1130

reduce函数可选的参数在第一个例子里是基本变量数字 0 ,但是它也可以是一个对象,数组… 而不仅是基本类型,之后我们将会看到。

现在,我们收到一个20$的优惠券。

1
2
3
var total = items.reduce(reducer,-20);

console.log(total); // 1110

进阶用法(结合)

第二种用法的例子是 ReduxcombineReducers 函数源码里用到的。

此创意是将 reducer 函数拆分为独立的函数,最后组合成一个新的单一的大 reducer 函数。

为了说明,我们创建一个单一的对象,包含一些可以计算不同货币($, €…)的总价值的 reducer 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var reducers = {
totalInDollar: function(state, item) {
state.dollars += item.price;
return state;
},
totalInEuros : function(state, item) {
state.euros += item.price * 0.897424392;
return state;
},
totalInPounds : function(state, item) {
state.pounds += item.price * 0.692688671;
return state;
},
totalInYen : function(state, item) {
state.yens += item.price * 113.852;
return state;
}
// more...
};

然后我们建立一个 reduce函数

  • 能够调用每一部分的 reduce函数
  • 返回一个新的 reducer 回调函数
1
2
3
4
5
6
7
8
9
10
11
var combineTotalPriceReducers = function(reducers) {
return function(state, item) {
return Object.keys(reducers).reduce(
function(nextState, key) {
reducers[key](state, item);
return state;
},
{}
);
}
};

现在,我们来看一下如何使用它。

1
2
3
4
5
6
7
8
9
10
11
var bigTotalPriceReducer = combineTotalPriceReducers(reducers);

var initialState = {dollars: 0, euros:0, yens: 0, pounds: 0};

var totals = items.reduce(bigTotalPriceReducer, initialState);

console.log(totals);

/*
Object {dollars: 1130, euros: 1015.11531904, yens: 127524.24, pounds: 785.81131152}
*/

我希望这种方法可以使你在自己的需求内使用 reduce() 函数时有新的想法。

使用 reduce 函数也可以实现保存每一次计算结果的功能。这在 Ramdajs 里的 scan 函数已经实现了。

在JSFiddle里运行
https://jsfiddle.net/darul75/81tgt0cd/

参考

关注【公众号】,了解更多。



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!