JavaScript 之 reduce

引言

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 存在,則該參數初值爲1array:
        返回調用 reduce() 方法的數組;

initialValue:
    可選的值,作爲第一次調用 callback 的初始值,賦值於 accumulator;

返回值

調用 reduce() 方法返回的值,即最後一次 callback 執行完的 accumulator 的值。

處理過程描述

第一次 callback 被調用, accumulatorcurrentValue 的值有兩種情況:

  1. 如果 initialValue 被傳入 reduce() 方法,accumulator 等於 initialValue 的值,currentValue 等於數組的第一個元素,同時 currentIndex 等於 0;

  2. 如果 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']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章