Array.prototype.reduce()数组
reduce() 方法对数组中的每一个元素执行一个reducer函数(升序执行),将其结果汇总为单个返回值。app
const arr1 = [1, 2, 3, 4]; const reducer = (accumulator, currentValue) => accumulator + currentValue; // 1 + 2 + 3 + 4 console.log(arr1.reduce(reducer)); // output: 10 // 5 + 1 + 2 + 3 + 4 console.log(arr1.reduce(reducer, 5)); // output: 15
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
1.参数
callback
执行数组中每一个值(若是没有提供 initialValue,则第一个值除外)的函数,包含四个参数:函数
accumulator
累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。this
currentValue
数组中正在处理的元素。prototype
index:可选
数组中正在处理的当前元素的索引。 若是提供了 initialValue,则起始索引号为0,不然从索引1起始。code
array:可选
调用reduce()的数组。对象
initialValue:可选
做为第一次调用 callback 函数时的第一个参数的值。 若是没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。索引
2.返回值
函数累计处理的结果。ip
回调函数第一次执行时,accumulator 和 currentValue 的取值有两种状况:
若是调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;
若是没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。input
注意:若是没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。若是提供initialValue,从索引0开始。
1.求出数组里全部值的和
let sum = [ 0, 1, 2, 3 ].reduce((acc, cur) => acc + cur, 0); console.log(sum); // 6
2.累加对象数组里的值
let total = [{x: 1}, {x:2}, {x:3}].reduce((acc, cur) => acc + cur.x, 0); console.log(total); // 6
3.将二维数组转化为一维
let flattened = [[0, 1], [2, 3], [4, 5]].reduce((acc, cur) => acc.concat(cur), []); console.log(flattened); // [0, 1, 2, 3, 4, 5]
4.计算数组中每一个元素出现的次数
let names = ['lxcan', 'splendid', 'ican', 'volcano', 'lxcan']; let countedNames = names.reduce((allNames, name) => { if (name in allNames) { allNames[name]++; } else { allNames[name] = 1; } return allNames; }, {}); console.log(countedNames); // { 'lxcan': 2, 'splendid': 1, 'ican': 1, 'volcano': 1 }
5.按属性对object分类
let peoples = [ { name: 'lxcan', age: 20 }, { name: 'ican', age: 20 }, { name: 'splendid', age: 18 } ]; function groupBy(arr, property) { return arr.reduce((acc, obj) => { let key = obj[property]; if (!acc[key]) { acc[key] = []; } acc[key].push(obj); return acc; }, {}); } let groupedPeople = groupBy(peoples, 'age'); console.log(groupedPeople); // { // 18: [{ name: 'splendid', age: 18 }] // 20: [ // { name: 'lxcan', age: 20 }, // { name: 'ican', age: 20 } // ], // }
6.使用扩展运算符和initialValue绑定包含在对象数组中的数组
// friends - 对象数组 let friends = [{ name: 'Anna', books: ['Bible', 'Harry Potter'], age: 21 }, { name: 'Bob', books: ['War and peace', 'Romeo and Juliet'], age: 26 }, { name: 'Alice', books: ['The Shining'], age: 18 }]; // allbooks - 包含全部朋友的书 + initialValue 中的附加列表 let allBooks = friends.reduce(function(prev, curr) { return [...prev, ...curr.books]; }, ['Alphabet']); console.log(allBooks); // ['Alphabet', 'Bible', 'Harry Potter', 'War and peace', 'Romeo and Juliet', 'The Shining']
7.功能型函数封装
const double = x => 2 * x; const triple = x => 3 * x; const quadruple = x => 4 * x; // 对功能函数进行封装 const pipe = (...functions) => { return input => functions.reduce((acc, fn) => fn(acc), input) }; // 用于特定值组合乘法的复合函数 const multiply6 = pipe(double, triple); const multiply9 = pipe(triple, triple); const multiply16 = pipe(quadruple, quadruple); const multiply24 = pipe(double, triple, quadruple); // 使用 multiply6(6); // 36 multiply9(9); // 81 multiply16(16); // 256 multiply24(10); // 240
8.使用 reduce 实现map
if (!Array.prototype.mapByReduce) { Array.prototype.mapByReduce = function(callback, thisArg) { return this.reduce(function(mappedArray, currentValue, index, array) { mappedArray[index] = callback.call(thisArg, currentValue, index, array); return mappedArray; }, []); }; } let arr = [1, 2, 3].mapByReduce((value, index, array) => value + index + array.length); console.log(arr); // [4, 6, 8]