引言
reduce 是 Array.prototype 中的一個方法,這個方法的作用是提供一個函數式的累加器,將數組中的每一個值進行累加最終減少到只有一個值。
先說說兼容性:
Chrome all、Firefor 3.0、IE 9 以上、Opera 10.5和 safari 4.0以上的版本均支持Array.prototype.reduce。
先看一個栗子:
const sum = [1, 2, 3, 4, 5].reduce( (acc, item) => acc + item, 0);
// sum = 6;
var list1 = [[0, 1], [2, 3], [4, 5]];
var list2 = [0, [1, [2, [3, [4, [5]]]]]];
const flatten = arr => arr.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
flatten(list1); // returns [0, 1, 2, 3, 4, 5]
flatten(list2); // returns [0, 1, 2, 3, 4, 5]
用法:
arr.reduce( callback [, initialValue] )
參數:
reduce()方法接收兩個參數,一個是callback(回調),另一個是可有可無的initialValue。
callback:
回調函數可以接收4個參數,分別是 accumulator、currentValue、currentIndex 和 array;
accumulator:
返回上一次 callback 運行返回的結果,或者是 initialVaule;
currentValue:
數組中,當前正在被處理的元素;
currentIndex:
數組中,當前正在被處理的元素的索引,起初爲0,如果 initialValue 存在,則該參數初值爲1;
array:
返回調用 reduce() 方法的數組;
initialValue:
可選的值,作爲第一次調用 callback 的初始值,賦值於 accumulator;
返回值
調用 reduce() 方法返回的值,即最後一次 callback 執行完的 accumulator 的值。
處理過程描述
第一次 callback 被調用, accumulator
和 currentValue
的值有兩種情況:
如果
initialValue
被傳入reduce()
方法,accumulator
等於initialValue
的值,currentValue
等於數組的第一個元素,同時currentIndex
等於0
;如果
initialValue
沒有傳入reduce()
方法,accumulator
等於數組第一個元素的值,currentValue
等於數組的第二個元素,同時currentIndex
等於1
;
請注意:
如果調用 `reduce()` 的數組爲空並且沒有傳入 `initialValue`, `TyepError`錯誤會被拋出。
若該數組只有一個元素(即:lenght 爲 1),並且 `initialValue` 還是沒有傳入 `reduce()` 方法
或者
若數組爲空,但是傳了 `initialValue`
`reduce()` 方法僅僅會返回單獨(可能是`initialValue` 或者 數組唯一的元素`)的值,但是請注意,這個方法並沒有執行 `callback` 的方法。
官方建議,initialValue
的值最好不要捨去,否則可能會產生三種不同的結果。
一大堆栗子
求數組中每個元素累加的和:
var sum = [0, 1, 2, 3].reduce(function(a, b) {
return a + b;
}, 0);
// sum = 6
// ES6 箭頭函數的寫法:
var total = [ 0, 1, 2, 3 ].reduce( ( acc, cur ) => acc + cur, 0 );
將多重數組轉換爲一維數組:
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
return a.concat(b);
}, []);
// flattened = [0, 1, 2, 3, 4, 5]
// ES6 箭頭函數的寫法:
var flattened = [[0, 1], [2, 3], [4, 5]].reduce( ( acc, cur ) => acc.concat(cur), [] );
統計數組中每個元素出現的次數,並轉換爲對象:
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce( (acc, cur) => {
if (acc.hasOwnProperty(cur)) {
acc[cur]++;
} else {
acc[cur] = 1;
}
return acc;
}, {});
// countedNames is { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
使用擴展運算符和 initialValue
,合併/數組中/每個對象/的/數組(比較繞,不好理解):
var 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 }
];
var allbooks = friends.reduce(function(prev, curr) {
return [...prev, ...curr.books];
}, ['Alphabet']);
// allbooks = ['Alphabet', 'Bible', 'Harry Potter', 'War and peace', 'Romeo and Juliet', 'The Lord of the Rings', 'The Shining']