General Function Wrapper Solution

date
Sep 27, 2023
slug
general-function-wrapper-solution
status
Published
tags
JavaScript
summary
type
Post
我們時常有需要包裝 function 的需求,例如你想在 function 開始前、結束時、報錯時做其他事情,亦或是調整 function 執行的時機 (ex. 常見的 debounce, throttle),這個時候我們就會寫一個 input 是 function,output 也是 function 的 function 出來。
💡
並不是所有程式語言都能做到「input 是 function、output 是 function」這件事,像是 C lang 就只能傳 pointer 來實作。也有專有的名詞來形容這類語言的 function 為 first-class function,一般也會使用這類的語言來撰寫 functional programming

常見的寫法

上面是一個沒做任何事情的 wrapper,其實這麼寫在大部分的 case 沒有問題,但如果有使用到 this 呢?
以上面的例子,因為實作時是使用 arrow function,所以 this 會是定義 wrapper() 時所指向的 window (在嚴格模式下會是 undefined),因此我們需要只用 bind/call/apply,讓執行 function 時的 this 指到預期的物件上。

修正後的寫法

預期的 this 會是執行 wrapper 吐出來的 function 時的呼叫端,因此我們不要 return arrow function,改成 return 一般的 function,以保留原本預期的 this 值。另外可以注意到我們有特別 assign this 到另一個變數上,在目前這個 case 中其實是不必要的,但如果今天執行 fn 是在 callback pattern 的情況下 (ex. setTimeout),那麼可能就需要先 assign 到另一個變數上,不然在 callback 裏拿到的 this 可能不會是預期的。

Typescript

理想上我們希望 input 和 output 有一樣的型別,因此我們需要使用 assertion
 

Real World Example: Debounce

 

© maxam 2023 - 2024