在前一章節中,我們花了很多的篇幅來聊 FP 這個程式設計的演進史,從中不難看出由於 JavaScript 的基因設定本來就會帶有多設計典範(Multi-paradigm)的特性。
這個特性導致我們在撰寫程式碼的過程中,無意識間會使用到不同設計典範的手段,而衍生出一些預期外的錯誤,或是我們常見的一些設計典範,如同目前我們討論的主角 FP ,並不一定能完全百分百適用進 JavaScript 這門語言。
關於會產生什麼樣類型的錯誤,及 JavaScript 與真正的 FP 導向語言差異在哪,我們會在後續的章節中繼續討論。
在這個章節,我們主要會針對 FP 這個設計典範的特性來做個簡單的介紹,如果你是第一次接觸這個設計典範的話,有些概念對你來說可能會很抽象、不好理解,這都是很正常的,接下來我們所提到的概念,也都會在後續的章節中一一進行介紹。
Functional Programming 中文譯作函式程式設計,或是功能性程式設計,常簡稱為:FP,是一種透過使用純函式(Pure Funciton)進行軟體開發,且避免狀態共用、副作用的程式設計典範,比起宣告式的流程控制,在 FP 採用主要以表達式的方式撰寫程式碼。
與物件設計導向設計相比,FP 設計不會透過實作物件的方式來撰寫程式碼,例如:封裝一個 class
或是原型,更別提繼承、擴充物件方法等實作方式,原因在於在 JavaScript 中使用物件且從中新增物件方法的話,就會有狀態共用的情況發生。
如果我們將 FP 這個設計典範的特點一一列點出來會有以下概念:
如果我們現在上網 Google 有關 FP 的相關資訊,這些艱深的詞彙可能會讓你想要打退堂鼓,即便對寫了一段時間 JavaScript 的開發者來來說,可能也不例外。
除了上述的基礎概念外,你可能還會相繼看到柯里化、Pipe 等進階應用概念,有個壞消息是:這些概念都與電腦科學的運算概念深深相關。
我們沒有辦法為了加快學習的腳步而任性的跳過任何一個概念,因為這樣可能就會「接不上」,就好像一幅拼圖一樣,少了任何一塊拼圖都沒有辦法看到 FP 這個設計典範完整的面貌,及想要解決什麼問題,或是者是說在 JavaScript 中導入 FP 可以解決什麼問題。
好在接下來的內容當中,我們不僅會一一針對以上概念進行深入的介紹,同時也會以 JavaScript 這門語言的切度切入,讓大家可以真的透過 JavaScript 實作 FP 這個設計典範。
針對這些概念一一介紹之前,讓我們先來看看以多設計典範為雛形的 JavaScript 有什麼與其他語言不同的特性,及會在開發上給我們造成些什麼影響吧!
我們下一章節見。
FP 並不避免狀態共用,相反地,FP 鼓勵狀態共用,畢竟 immutable 的天性,沒有狀態變更問題,共用也就沒有問題。
FP 定義類別或使用物件,並沒有什麼問題,事實上有些語言裡,像是 Scala,就會這麼做,新增物件跟狀態共用也沒什麼直接關係。
謝謝大大的回饋!
這邊主要是參考 Eric Elliot 針對 JavaScript 所撰寫的 Composing Software 一書,由於 JavaScript 的物件是 Mutable 的(在沒有使用 TS 的狀況下),所以作者才提及在原生 JS 要特別避開共用同一個物件的狀況,但確實新增物件與狀態共用是兩件事,後續會再把內文做修正,感謝大大的不吝指教
在沒有編譯器或轉譯器協助施加限制的情況下,想在 Imperative programming 的語言裡實現 FP,最基本的只要記得一個自我約束:
不要對既有的變數或資料結構實例進行更新,如果系統需要新狀態,那就用新的變數或資料結構實例來承載。
從 Imperative programming 的語言裡實現 FP,很容易會有許多東西看不清楚,有機會建議學習一門純函數式語言,就可以避免那些 Imperative programming 的雜訊(像是「作者才提及在原生 JS 要特別避開共用同一個物件的狀況」,那是怕你受不到誘惑,直接對物件進行狀態更新,而不是建立新物件承載新狀態,這類雜訊,本質上並不是 FP 的元素),看清更多概念。
非常感謝大大的分享
這樣子我理解了,後續也會再將內文的敘述做修正,非常感謝大大的耐心指教!