reduce()方法对数组中的每个元素按序执行一个函数,每一次运行会将先前元素的计算结果作为参数传入,最后将结果汇总为单个返回值.
参数:
????????????????第一个参数是回调函数,该函数接受4个参数:
?????????????????????????previousValue: 上一次调用回调函数的返回值.
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第一次调用,如果有默认值,则值时默认值,否则值时array[1]
????????????????????????currentValue: 数组中正在处理的元素.
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第一次调用,如果指定初始值,则值是array[0], 否则为array[1]
????????????????????????currentIndex: 数组中正在处理的元素索引.
????????????????????????????????????????????????如果指定默认值,则开始索引为0,否则为1
????????????????????????array: 用于遍历数组
? ? ? ? ? ? ? ? 第二个参数是previousValue的默认值.
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 如果指定了默认值,则currentValue使用数组的第一个元素
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 否则previousValue将使用数组第一个元素,儿currentVale使用第二个元素
返回值:? 使用回调函数遍历整个数组后的结果.
数组为空且初始值未提供会报错
数组长度为空和为1的情况:
? ? ? ? 1.数组长度为空:? 如果提供默认值但是数组为空,回调函数不会被执行.? ? ? //TypeError
? ? ? ? 2.数组长度为1:? 如果数组仅有一个元素,并且没有提供默认值.? ? ? ? ? ? ? ? ? //TypeError
没有参数时reduce()如何运行
? 运行一下无初始值的reduce()代码:
const array = [15, 16, 17, 18, 19];
function reducer(previous, current, index, array) {
const returns = previous + current;
console.log(`previous: ${previous}, current: ${current}, index: ${index}, returns: ${returns}`);
return returns;
}
array.reduce(reducer);
?
?有默认值时reduce()如何工作
?示例:
求数组所有值得和
let sum = [0, 1, 2, 3].reduce(function (previousValue, currentValue) {
return previousValue + currentValue
}, 0)
// sum is 6
也可以写成箭头函数
let total = [ 0, 1, 2, 3 ].reduce(
( previousValue, currentValue ) => previousValue + currentValue,
0
)
累加对象数组里的值
要累加对象数组中包含的值,必须提供默认值,以便各个 item 正确通过你的函数。
let initialValue = 0
let sum = [{x: 1}, {x: 2}, {x: 3}].reduce(function (previousValue, currentValue) {
return previousValue + currentValue.x
}, initialValue)
console.log(sum) // logs 6
// 以下是箭头函数的写法
let initialValue = 0
let sum = [{x: 1}, {x: 2}, {x: 3}].reduce(
(previousValue, currentValue) => previousValue + currentValue.x
, initialValue
)
console.log(sum) // logs 6
将二维数组转为一维数组
let flattened = [[0, 1], [2, 3], [4, 5]].reduce(
function(previousValue, currentValue) {
return previousValue.concat(currentValue)
},
[]
)
// flattened is [0, 1, 2, 3, 4, 5]
// 箭头函数写法
let flattened = [[0, 1], [2, 3], [4, 5]].reduce(
( previousValue, currentValue ) => previousValue.concat(currentValue),
[]
)
计算数组中每个元素出现的次数
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']
let countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
allNames[name]++
}
else {
allNames[name] = 1
}
return allNames
}, {})
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
按属性对Object分类
let people = [
{ name: 'Alice', age: 21 },
{ name: 'Max', age: 20 },
{ name: 'Jane', age: 20 }
];
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
let key = obj[property]
if (!acc[key]) {
acc[key] = []
}
acc[key].push(obj)
return acc
}, {})
}
let groupedPeople = groupBy(people, 'age')
// groupedPeople is:
// {
// 20: [
// { name: 'Max', age: 20 },
// { name: 'Jane', age: 20 }
// ],
// 21: [{ name: 'Alice', age: 21 }]
// }
使用扩展运算符和默认值绑定包含在对象数组中的数组
// 对象字段“books”是最喜欢的书的列表
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 Lord of the Rings', 'The Shining'],
age: 18
}]
let allbooks = friends.reduce(function(previousValue, currentValue) {
return [...previousValue, ...currentValue.books]
}, ['Alphabet'])
// allbooks = [
// 'Alphabet', 'Bible', 'Harry Potter', 'War and peace',
// 'Romeo and Juliet', 'The Lord of the Rings',
// 'The Shining'
// ]
数组去重
let myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd']
let myArrayWithNoDuplicates = myArray.reduce(function (previousValue, currentValue) {
if (previousValue.indexOf(currentValue) === -1) {
previousValue.push(currentValue)
}
return previousValue
}, [])
console.log(myArrayWithNoDuplicates)
使用reduce() 替换 filter()和map()
这个案例: 如果用filter和map做的话,就要执行两个循环了.但是一个reduce就解决.
如果你喜欢forEach的话,也可以再一次循环中实现
const numbers = [-5, 6, 2, 0];
const doubledPositiveNumbers = numbers.reduce((previousValue, currentValue) => {
if (currentValue > 0) {
const doubled = currentValue * 2;
previousValue.push(doubled);
}
return previousValue;
}, []);
console.log(doubledPositiveNumbers); // [12, 4]
按顺序运行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
使用reduce实现map
if (!Array.prototype.mapUsingReduce) {
Array.prototype.mapUsingReduce = function(callback, initialValue) {
return this.reduce(function(mappedArray, currentValue, currentIndex, array) {
mappedArray[currentIndex] = callback.call(initialValue, currentValue, currentIndex, array)
return mappedArray
}, [])
}
}
[1, 2, , 3].mapUsingReduce(
(currentValue, currentIndex, array) => currentValue + currentIndex + array.length
) // [5, 7, , 10]
?
|