reduce()
方法将数组中的元素缩减为一个值,返回的这个值可以是任何类型。
reduce()
就像数组方法瑞士军刀。像 map()
和 filter()
之类的方法有特定的功能,而 reduce()
可以将输入数组转换为所需的任何输出,同时保留原始数组。
语法
const newValue = arr.reduce(function(accumulator, currentValue, index, array) {
// Do stuff with accumulator and currentValue (index, array, and initialValue are optional)
}, initialValue);
newValue
- 返回的新的数字、数组、字符串或对象arr
- 对其执行操作的数组accumulator
- 上一个遍历返回的值currentValue
- 数组中的当前元素index
- 当前元素的索引array
- 调用reduce()
的原始数组initialValue
- 传递给函数的初始值,可以是一个数字、数组、字符串或对象
示例
ES5
var numbers = [1, 2, 3];
var sum = numbers.reduce(function(total, current) {
return total + current;
}, 0);
console.log(numbers); // [1, 2, 3]
console.log(sum); // 6
ES6
const numbers = [1, 2, 3];
const sum = numbers.reduce((total, current) => {
return total + current;
}, 0);
const sumOneLiner = numbers.reduce((total, current) => total + current, 0);
console.log(numbers); // [1, 2, 3]
console.log(sum); // 6
console.log(sumOneLiner); // 6
关于 initialValue
含有 initialValue
initialValue
参数是可选的。如果有,它是作为回调函数第一次调用后的初始值(计算结束后的返回值 total
):
const numbers = [2, 3, 4];
const product = numbers.reduce((total, current) => {
return total * current;
}, 1);
console.log(product); // 24
因为有 initialValue
为 1,reduce()
从数组的开头开始,将第一个元素(2)设置为当前元素(current
)。然后遍历数组的剩余部分,同时更新累计值和当前元素。
没有 initialValue
如果没有 initialValue
,遍历将从数组的第二个元素(索引为 1)开始,accumulator
等于数组的第一个元素,而 currentValue
等于数组的第二个元素:
const numbers = [2, 3, 4];
const product = numbers.reduce((total, current) => {
return total * current;
});
console.log(product);
在这个例子中,没有 initialValue
,所以 reduce()
将数组的第一个元素设置为累计值(total
等于 2),将数组的第二个元素设置为当前元素(currentValue
等于 3)。然后遍历数组的其余部分。
当缩减一个字符串数组时:
const strings = ['one', 'two', 'three'];
const numberString = strings.reduce((acc, curr) => {
return acc + ', ' + curr;
});
console.log(numberString); // "one, two, three"
如果 reduce()
方法将返回一个数字或一个简单的字符串,那么很容易省略 initialValue
参数。如果是返回一个数组或对象,那么应该含有 initialValue
参数。
返回一个对象
将字符串数组转换为一个对象很简单,该对象可以显示每个字符串在数组中出现的次数。只需传递一个空对象({}
)作为 initialValue
:
const pets = ["dog", "chicken", "cat", "dog", "chicken", "chicken", "rabbit"];
const petCounts = pets.reduce(function(obj, pet) {
if (!obj[pet]) {
// if the pet doesn't yet exist as a property of the accumulator object,
// add it as a property and set its count to 1
obj[pet] = 1;
} else {
// pet exists, so increment its count
obj[pet]++;
}
return obj; // return the modified object to be used as accumulator in the next iteration
}, {}); // initialize the accumulator as an empty object
console.log(petCounts);
/*
{
dog: 2,
chicken: 3,
cat: 1,
rabbit: 1
}
*/
返回一个数组
通常,如果你要返回一个数组,那么 map()
是一个更好的选择。它告诉编译器(和其他阅读你的代码的人)原始数组中的每个元素都将被转换,并以等长的新数组形式返回。
另一方面,reduce()
表示原始数组的所有元素都将被转换为新值。该新值可以是一个数组,其长度可能与原始数组不同。
假设你有一个购物清单,其中包含字符串,但你想从清单中删除所有不喜欢的食物,那么你可以使用 filter()
过滤掉所有不喜欢的内容,并使用 map()
返回新的字符串数组,也可以只使用 reduce()
:
const shoppingList = ['apples', 'mangoes', 'onions', 'cereal', 'carrots', 'eggplants'];
const foodsIDontLike = ['onions', 'eggplants'];
const newShoppingList = shoppingList.reduce((arr, curr) => {
if (!foodsIDontLike.includes(curr)) {
arr.push(curr);
}
return arr;
}, []);
console.log(newShoppingList); // ["apples", "mangoes", "cereal", "carrots"]
以上就是有关 reduce()
方法的全部知识。它就像瑞士军刀一样,并不总是工作的最佳工具,但是当你真正需要它时,你会很高兴背后的口袋中有它。