最近在项目里抠语言包的过程中发现做了很多重复的工作,然后同事指点了一下reduce这个方法,仿佛打开了新世界的大门。遂重新学习了一下reduce的用法。在博客记录一下。
提示:努力想把文章写的精简,但是觉得关于这个函数很多细节想写。所以这篇观感可能会是: 博主是个bb怪。
测试:
如果你能理解下列函数的原理,那么这篇文章你完全没有阅读必要。
// 版本1
[...new Array(100).values()].map((item, index) => index + 2).reduce((a, b) => `${a} MINE_${b}: "", \n`, 'MINE_1: "",');
// 另一种写法
[...new Array(100).toString().split(',').keys()].reduce((a, b) => `${a} MINE_${b}: "", \n`,'');
一、定义
array.reduce( function(accumulator, currentValue
, currentIndex, array), initialValue );
accumulator:上一次调用回调返回的值,或者是提供的初始值(initialValue)
currentValue:数组中正在处理的元素
currentIndex:数据中正在处理的元素索引,如果提供了 initialValue ,从0开始;否则从1开始。【可选】
array: 调用 reduce 的数组【可选】
initialValue:可选项,其值用于第一次调用 callback 的第一个参数。如果没有设置初始值,则将数组中的第一个元素作为初始值。【可选】这里注意如果对一个空数组使用 [ ].reduce 方法会报错。原因看下面例子。
array.reduce 的返回值是这个函数累计处理的结果。
// 用代码解释定义
let demo = [ 333, 222, 111 ];
//没有定义initialValue
demo.reduce((acc, curVal) => { console.log(acc) })
// 输出: 333, undefined, undefined
//定义initialValue为1
demo.reduce((acc, curVal) => { console.log(acc)}, 1)
// 输出: 1, undefined, undefined
//空数组不定义initialValue
[].reduce((a,b) => console.log(a))
// 输出:Uncaught TypeError: Reduce of empty array with no initial value
// 因为没有定义初始值,a会默认取数组第一个值,而空数组,第一个值是undefined,所以报错。
/* 说明:回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。输出中有undefined 是因为acc返回的是上一次函数返回的结果,但这里我们函数仅是打印,没有返回值,所以是undefined */
二、它可以方便的做一些事
数组求和
将数组转化为对象、计算数组中每个元素出现的次数、按属性对数组分类
按顺序运行promise
2.1 数组求和
let demo = [ { x: 1}, { x: 2 }, { x: 3} ],
demo.reduce((arr,val) => { return arr + val.x }, 0);
// return: 6
2.2 数组转化为对象
let demo = [
{
id: 1,
username: 'john',
sex: 1,
email: 'john@163.com'
},
{
id: 2,
username: 'jerry',
sex: 1,
email: 'jerry@163.com'
},
{
id: 3,
username: 'nancy',
sex: 0,
email: ''
}
];
demo.reduce( (acc,val) => { return {...acc, [val.username]: val} } , {} )
2.3 按顺序执行promise
/**
* 直接抄官网的例子
* Runs promises from array of functions that can return promises
* in chained manner
*
* @param {array} arr - promise arr
* @return {Object} promise object
*/
function runPromiseInSequence(arr, input) {
return arr.reduce(
(promiseChain, currentFunction) => promiseChain.then(currentFunction),
Promise.resolve(input)
);
}
// promise function 1
function p1(a) {
return new Promise((resolve, reject) => {
resolve(a * 5);
});
}
// promise function 2
function p2(a) {
return new Promise((resolve, reject) => {
resolve(a * 2);
});
}
// function 3 - will be wrapped in a resolved promise by .then()
function f3(a) {
return a * 3;
}
// promise function 4
function p4(a) {
return new Promise((resolve, reject) => {
resolve(a * 4);
});
}
const promiseArr = [p1, p2, f3, p4];
runPromiseInSequence(promiseArr, 10)
.then(console.log); // 1200
2.4 数组去重
reduce当然也能做到,但是我更喜欢下面这个方式
let demo = [ 1, 1, 2, 3];
//一行完成数组去重并升序排序
[...new Set(demo)].sort();
参考链接:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce