---
url: /blog-program/remeda-piped-references-problem.md
description: 使用 remeda piped 時，不小心給自己埋了地雷，來筆記一下。(。-`ω´-)
---

![remeda-piped-references-problem](/remeda-piped-references-problem.webp){.cover}

# remeda piped 之 reference 問題

remeda 提供了一個 [`piped`](https://remedajs.com/docs/#piped) function，可以更方便的組織函數，不過我在使用時遇到了一個問題。

::: tip 甚麼是 Remeda
不知道甚麼是 Remeda 的朋友，可以參考我之前的文章：[好 pipe 不用嗎？藉由 remeda 讓程式碼更簡潔彈性吧！](https://codlin.me/blog-program/remeda-pipe)
:::

考慮以下程式：

```ts
const getList1 = R.piped(
  R.reduce((acc, item) => acc, [])
)

function getList2(list) {
  return R.pipe(
    list,
    R.reduce((acc, item) => acc, [])
  )
}
```

乍看之下，這兩個函數效果相同，但實際上 `getList1` 有一個大坑。

大家猜猜看是甚麼坑？

提示：不是 `remeda` 的問題，是 JS 本身的特性。

還沒看出問題的朋友不用擔心，[實際跑跑看就知道](https://stackblitz.com/edit/piped-reference-issue?file=index.js)了。%( ´ ▽ \` )ﾉ%

## 結果

`getList1` 回傳的結果都是同一個記憶體位置，也就是說，每次呼叫 `getList1` 都會得到同一個陣列。%Σ(ˊДˋ;)%

至於為甚麼，讓我們換個寫法就能理解了，`getList1` 的寫法等校於：

```ts
const initValue = []
const getList1 = R.piped(
  R.reduce((acc, item) => acc, initValue)
)
```

問題在於 `getList1` 的初始值變成一個全域變數，所以每次呼叫 `getList1` 都會得到同一個陣列。

`getList2` 由於初始值的 `[]` 在 function 呼叫時才初始化，所以沒有此問題。

大家在使用 `piped` 時，要特別注意這個問題，以免埋了一個巨大的地雷喔。%(´,,•ω•,,)%

::: tip
補充一個 `remeda` 開發者的[討論](https://github.com/remeda/remeda/issues/1030)，有興趣的人可以一起參與討論。%੭ ˙ᗜ˙ )੭%
:::

## 總結 🐟

* 使用 `piped` 要特別注意可能的 reference 問題。
* 這個不是 `remeda` 的問題，而是 JS 本身的特性。
