# [IM011] Reduce
> **前言**
> 2020 秋天,我將用 30 天的時間,來嘗試回答和網路前端開發相關的 30 個問題。30 天無法一網打盡浩瀚的前端知識,有些問題可能對有些讀者來說相對簡單,不過期待這趟旅程,能幫助自己、也幫助讀者打開不同的知識大門。有興趣的話,跟著我一起探索吧!
>

## Reduce
Map, Filter, Reduce 是 JavaScript array 當中三種常用的方法。Map 的目的是遍歷所有 item,經過處理之後,回傳同樣長度的陣列;filter 同樣是遍歷所有 item,但是回傳符合條件的 items。
不過 Reduce 的功能就更為強大了,不僅僅有累加的功能,更可以實現 map 和 filter 的功能,可以說應用場景非常的廣。
所以,今天就來特別介紹一下 reduce 方法。
## Syntax
reduce 的基本結構如下:
```javascript=
array.reduce((acc, cur, index, array) => {
// do something
return acc
}, initialValue)
```
除了一般 array method 當中 callback function 會接收的
* cur (current value)
* index
* array ( array 自己本身)
之外,還多了一個 acc (accumulator),中文是累加器的意思。這個累加器會接收上一次迭代後的回傳值,所以通常 callback function 裡面會 return acc,作為下一次迭代的 arr 值。
這個 acc 可以是 number, string, array 甚至是 object,因此操作的彈性非常大!
等等,那第一次迭代當中, acc 會是什麼?
第一次迭代當中,沒有機會接收到上一次迭代的回傳值,因此這時候的 acc 會有兩種情況:
**1. 有設定 initialValue**
在有設定 initialValue 的情況下,acc 就會是這個 initialValue,同時,reduce() 就會從 array[0] 開始迭代。
```javascript=
let array = [0, 1, 2, 3, 4]
array.reduce((acc, cur, index, array) => {
acc += cur
return acc
}, 99)
```
在第一次迭代當中,acc, cur, index 分別為 99, 0, 0,在 callback function 當中執行 acc + cur 並回傳 acc,因此,在第二次的迭代當中 acc, cur, index 分別為 99, 1, 1,以此類推
**2. 沒有設定 initialValue**
如果沒有設定 initialValue 的話,acc 預設為 array 的第一個值,同時,reduce 就會從 array[1] 開始迭代。以下面這個例子來說
```javascript=
let array = [0, 1, 2, 3, 4]
array.reduce((acc, cur, index, array) => {
acc += cur
return acc
})
```
在第一次迭代當中,acc, cur, index 分別為 0, 1, 1,然後回傳結果 1 ;在第二次的迭代當中 acc, cur, index 則為 1, 2, 2,以此類推。
## 基本累加功能
一開始設定累加器 acc 為 0,接著,在每一次的迭代當中,把 cur (curren value) 加入到 acc 當中:
```javascript=
let array = [0, 1, 2, 3, 4]
array.reduce((acc, cur) => {
acc += cur
return acc
}, 0)
```
## 實現 map 功能
map() 可以幫助我們轉化 array 當中的所有 elements,譬如全部乘以 2 並回傳結果陣列
```javascript=
let array = [0, 1, 2, 3, 4]
array.map(item => item * 2) // [ 0, 2, 4, 6, 8 ]
```
這裡我們也可以用 reduce() 來做到!只要設定 acc 初始值為一個 empty array,在每一次的迭代放入 cur 乘以 2 的結果
```javascript=
let array = [0, 1, 2, 3, 4]
array.reduce((acc, cur) => {
acc.push(cur * 2)
return acc
}, [])
```
最後可以得到一個同樣的結果
## 實現 filter 功能
如果要篩選出 array 當中的偶數,只要在 callback function 當中透過 if/else 來篩選出我們要的 element,然後再放入 acc 這個 array 當中,就可以得到我們想要的結果囉
```javascript=
let array = [0, 1, 2, 3, 4]
array.reduce((acc, cur) => {
if (cur % 2 === 0) {
acc.push(cur)
}
return acc
}, [])
```
## 實現 join 功能
其實用 join() 就很方便了,不過這裡只是想示範 reduce() 可以做很多種事情。如果我們想要達到 array.join('-') 的效果,可以這麼做:
```javascript=
let array = ['this', 'is', 'a', 'book']
array.reduce((acc, cur, index) => {
if (index === 0) return acc = cur
acc += '-' + cur
return acc
},'')
```
會得到結果 `"this-is-a-book"`
## 其他應用
如果我們要同時計算 array 當中所有數值的總和與平均,這裡我們可以使用 reduce() 一口氣完成:
```javascript=
let array = [0, 1, 2, 3, 4]
let result = array.reduce((acc, cur, index) => {
acc.sum += cur
acc.avg = (acc.avg * (index) + cur)/(index + 1)
return acc
}, {sum: 0, avg: 0})
```
這裡我設定 arr 的初始值為一個 object,當中分別紀錄總和與平均的值。最後可以得到結果 `{ sum: 10, avg: 2 }`
## End
## Ref
* [Array.prototype.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
***
> **TD**
> Be curious as astronomer, think as physicist, hack as engineer, fight as baseball player
> [More about me](https://tsungtingdu.github.io/profile/)
>
> *"Life is like riding a bicycle. To keep your balance, you must keep moving."*
***
###### tags: `ironman` `javascript`