reduce函数是JavaScript的数组函数中,功能比较强大的函数。但是大部分博文对reduce函数的解释都是比较和基础。
reduce的基础用法
我们先来看看reduce的基础用法,由于reduce的基础用法,在MDN里有比较详尽的解释,所以建议各位直接去看MDN
JavaScript | MDN | Array.prototype.reduce()
里面有几个比较典型的例子
例1.数组去重:
var myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd'];
var myOrderedArray = myArray.reduce(function (accumulator, currentValue) {
if (accumulator.indexOf(currentValue) === -1) {
accumulator.push(currentValue);
}
return accumulator
}, [])
console.log(myOrderedArray);
实际上,如果不用Set,咋一看可以用filter实现,但是由于filter拿不到迭代的结果array,所以用filter或者forEach、map实现都需要借助外部定义的数组,比如
var myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd'];
var resultArray = [];
myArray.forEach(item => {
if(resultArray.indexOf(item) === -1){
resultArray.push(item);
}
})
例2.迭代使用Promise
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
reduce的特点就是在迭代过程中,可以使用之前的迭代结果
所以我们得出第一个结论:
迭代过程中,需要使用到迭代结果的,适合使用reduce
反之,如果迭代过程中,不需要使用迭代结果,那么Array.prototype上的其他函数,完全可以胜任任何逻辑。
例3:把originArray数组变成一个一维数组
let originArray = [1,[2,3],[4,[5,6,[7,8],9],10,[11,12,[13,14],15],16],17];
function smoothArray(array){
return array.reduce((resultArray, currentValue) => {
let concatArray;
if(Array.isArray(currentValue)){
concatArray = smoothArray(currentValue);
}else{
concatArray = [currentValue];
}
return resultArray.concat(concatArray);
}, [])
}
smoothArray(originArray);
// 结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
本例中,我们通过递归的方式,将N维数组originArray降维变成了一维数组。
显而易见地,如果要把originArray变成一个0维数组(0维数组就是一个值),通过这个方法也是可行的。变成0维数组(一个值)的方式,可以是累加、累乘、累减等方法。在这里,用什么方法是不重要的,重要的是reduce干了什么、什么是reduce的本质。
什么是reduce的本质?
抽象地,reduce的调用者一定是一个数组,这个数组至少是一个一维数组。得到的结果是一个值,这个值可能是数组,可能是对象,可能是JavaScript基础类型中的一个值。
reduce做的事情,是:
数组 => 一个值
我们和Array.prototype上的其他函数做个比较,可以发现,map、forEach、filter一定返回一个数组;includes、find、findIndex必然返回一个值;reduce做的,是将一个高维度的东西,“压缩”成一个值的过程。
读过《三体》的朋友,一定对《三体III》中描述的四维文明、以及太阳系二维化的情节有印象。降维的过程,几乎必然伴随着信息的丢失。reduce也不例外。当你将一个数组通过reduce变成一个值的时候,或多或少,必然丢失了一些信息。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。