---
# System prepended metadata

title: '[IM011] Reduce'
tags: [javascript, ironman]

---

# [IM011] Reduce

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

## 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`