callbackFn里面有4个参数,
- accumulator: 上一次调用callbackFn的结果,在第一次调用时候,如果指定流initialValue,则为指定的值,否则为array[0]
- currentValue: 在第一次调用时候,如果指定流initialValue,则为array[0],否则array[1]
- currentIndex: 在数组中的索引位置,在第一次调用时,如果指定了initialValue,则为0,否则为1
- array:调用了reduce数组本身
1、如果没有initialValue,reduce会从索引1开始执行回调,跳过第一个索引
2、对空数组调用reduce且不提供初始值会抛出TypeError
3、reduce不会改变原数组,而是返回一个新值
// 求和
const a1 = [1,2,3,4,5,6];
const result1 = a1.reduce((acc, cur) => acc+cur, 0);
console.log('result1', result1);
// 数组扁平化
const a2 = [[1,2,3], [4,5,6]]
const result2 = a2.reduce((acc, cur) => acc.concat(cur), [])
console.log('result2', result2)
// 找出最大值
const a3 = [1,2,3];
const r3 = a3.reduce((acc, cur) => Math.max(acc, cur), -Infinity);
console.log('r3', r3)
// 统计元素出现次数
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const r4 = fruits.reduce((acc, cur) => {
acc[cur] = (acc[cur] || 0) +1;
return acc;
}, {})
console.log('r4', r4)
// 按属性分组对象数组
const people = [
{name: 'Alice', age: 21},
{name: 'Bob', age: 20},
{name: 'Charlie', age: 21}
];
const r5 = people.reduce((acc, cur) => {
const key = cur.age;
if(!acc[key]) {
acc[key] = []
}
acc[key].push(cur);
return acc;
}, {})
console.log('r5', r5);
//链式调用
//伪代码
const promises = [promise1, promise2, promise3];
const r6 = promises.reduce((acc, cur) => {
return acc.then(cur)
}, Promise.resolve());
console.log('r6', r6)
自定义一个reduce
//自定义一个reduce
function myReduce(array, fn, initialValue) {
if(typeof fn !== 'function') {
throw new TypeError('必须是个function')
}
if(array.lenght === 0 && initialValue === undefined) {
throw new TypeError('数组为空且没有初始值')
}
let startIndex;
let acc;
if(initialValue !== undefined) {
acc = initialValue;
startIndex = 0;
} else {
acc = array[0];
startIndex = 1;
}
for(let i = startIndex; i< array.length; i++) {
acc = fn(acc, array[i], i, array)
}
return acc;
}