Skip to content

remeda piped 之 reference 問題

remeda-piped-references-problem

remeda 提供了一個 piped function,可以更方便的組織函數,不過我在使用時遇到了一個問題。

甚麼是 Remeda

不知道甚麼是 Remeda 的朋友,可以參考我之前的文章:好 pipe 不用嗎?藉由 remeda 讓程式碼更簡潔彈性吧!

考慮以下程式:

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 本身的特性。

還沒看出問題的朋友不用擔心,實際跑跑看就知道了。( ´ ▽ ` )ノ

結果

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

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

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

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

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

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

TIP

補充一個 remeda 開發者的討論,有興趣的人可以一起參與討論。੭ ˙ᗜ˙ )੭

總結 🐟

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