# reduce() 是什麼?該如何使用?
昨天在面試時突然被問到有沒有使用過 reduce,一時之間腦內跑馬燈走過,有聽過這個字但好像沒有實際使用過,於是模稜兩可的給了一個很爛的回答,讓人後悔至極,應該大方承認自己沒有相關使用經驗,至少還比較有臺階可下。不過也因為如此,讓我發現自己對這個陣列的操作方法還不熟,趕緊來補強一下。
## Array.prototype.reduce()
根據 MDN 的說明,reduce() 方法將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。其實這個描述挺寫實的,不過我們搭配實作來看會更清楚。
### Syntax
```javascript=
array.reduce(function(accumulator, currentValue, currentIndex, array),initialValue)
```
其中有 4 個參數,分別代表不同的意思。
* accumulator:累加總計
* currentValue:目前值
* currentIndex(optional):這一輪迭代的索引(index)
* array(optional):陣列內容
而 `initialValue` 則是代表第一次要傳入的`初始值`。
### 實例 1
```javascript=
const array = [1, 3, 4, 5]
const arrayReduced = array.reduce((accumulator, currentValue) => {
return accumulator + currentValue
}, 5) //初始值為 5
console.log(arrayReduced) // 18
```
| No | accumulator | currentValue | currentIndex | return value |
|:---:|:-----------:|:------------:|:------------:|:------------:|
| 1 | 5 | 1 | 0 | 6 |
| 2 | 6 | 3 | 1 | 9 |
| 3 | 9 | 4 | 2 | 13 |
| 4 | 13 | 5 | 3 | 18 |
可以發現當我們的初始值是 5 的時候,`accumulator` 就是從 5 開始計算,後面接續 `currentValue` 的值累計。
### 實例 2
reduce() 也可以用來合併陣列。
```javascript=
const array = [[1, 3, 4, 5], [6, 7, 8], [9, 10, 11]]
const arrayReduced = array.reduce((accumulator, currentValue) => {
return accumulator.concat(currentValue)
}, [])
console.log(arrayReduced) // [1, 3, 4, 5, 6, 7, 8, 9, 10, 11]
```
或者來計算相同字串的數量並以物件呈現。
```javascript=
const array = ['apple', 'orange', 'orange', 'apple', 'apple', 'banana']
const arrayReduced = array.reduce((accumulator, currentValue) => {
if (currentValue in accumulator) {
accumulator[currentValue]++
} else {
accumulator[currentValue] = 1
}
return accumulator
}, {})
console.log(arrayReduced) // {apple: 3, orange: 2, banana: 1}
```
`reduce` 的 `initialValue` 可以設為任一型態(數值、物件、陣列),而 `accumulator` 可繼承 `initialValue` 的型態並接收 `currentValue` 計算後的結果。
## 結論
* 使用 `reduce` 可以進行比較細膩的比對與操作,尤其在陣列的 item 與 item 之間。
* 執行前記得確認 `initialValue`,因為他會決定累加器的初始值,影響 return 的結果。