JavaScript: Functional Programming 函式編程概念
在軟體工程開發的領域中,我們為了解決不同的問題,因此衍生出許多不同的程式設計(Programming paradigm)方式,這些設計方法彼此之間並沒有所謂的好壞、優劣,只有解決問題適合度高低的差異。
函式編程(Functional Programming,以下簡稱FP)是眾多程式設計(Programming Paradigm)方式的其中一種,有別於老早就大紅大紫的物件導向編成(object-oriented Programming,OOP)方式(OO還衍伸出許多設計模式(Design Patterns)),FP則是近年來較為熱門的程式設計方式。像是 React 這套 JavaScript 框架就是使用FP來開發程式,因此若想學習 React.js 勢必也要熟悉FP的基本概念,而 JavaScript 程式語言也需要符合FP的編程理念。以下將以 JavaScript 作為出發,解釋 JavaScript 函式編程的重要概念。
本篇文章您將會知道
- First-class and higher-order functions
- Pure Functions
- Declarative vs Imperative
*備註:以下皆以JavaScript為範例。
First-class and higher-order functions
First-class(一等公民) — 我們可以想像成對待函式(Functions)如同對待其他資料型別一樣。例如:可以直接賦予值或者存至陣列中當作參數傳遞。例如,我們可以宣告const a = 1,1 的值也就指定給 a,因此我們也可以直接將函式(Functions)指定給任一變數 const a = (x,y) => x * y,a 也就變成(x * y) Function 的變數,呼叫 a(2, 4) 則會返回值8。
higher-order functions(高階函式) — 在維基百科中高階函式至少會滿足下列其中一項條件
- 可以將函式(至少一個)當成參數傳入另一個函式。
- 可以將函式當成另一個函式的回傳值。
由上述範例我們可以得知,add函式接收參數 (x) 並且回傳一個函式 ( x + y ) 作為回傳值。因此在宣告addFive 變數時,同時給定 x=5 至 add 函式,往後使用 addFive 變數(函式變數)皆會從 5 開始加減。
上述則是符合higher-order functions的例子,add函式(Functions)接收參數並且回傳一個函式(Functions)作為回傳值。
Pure Functions
Pure Functions(純函式) —意指將相同的input丟入函式,永遠會回傳相同的output結果,而且在過程中完全沒有任何的副作用。此處的副作用通常意味著「避免狀態改變」、「避免資料改變」,我們可以想成不與函式區塊域(block)以外的變數做互動(最典型的例子,修改全域變數的值),或者不論函式以外做了什麼,函式(Functions)內的運算依舊不受改變。換句話說,Pure Functions擅於純運算,而不做其他事情(ex. 讀取外部資料)。範例如下:
在FP中,slice 函式(Functions)就符合我們Pure Functions的規範,相同input,永遠回傳相同output且無副作用。而splice函式(Functions)則是每次呼叫,output以及原始資料皆會不相同,因此不算是Pure Functions。
副作用
以JavaScript為例, 副作用還包括:
- 更改外部變數或者物件屬性(例如:全域變數、父類別範圍內的變數等)
- 寫入console.log、檔案
- 觸發外部流程
- 呼叫任何有副作用的函式(Functions)
Declarative vs Imperative
函式編程(Functional Programming)屬於宣告式編程(Declarative Paradigm)的一種,其程式邏輯
宣告式編程(Declarative Paradigm) 一 較為抽象的程式碼,可以藉由自然語言直觀的理解該行程式碼想要達到什麼樣的結果。描述該在哪做什麼(what to do)以及資料流程(data flow)。
指令式編程(Imperative Paradigm) 一 程式碼具體表達需要做什麼來達到目標。描述該做什麼(how to do)以及流程控制(flow control)。
宣告式編程(Declarative Paradigm)較依賴表達式(expression),表達式是一個單純的運算過程,並且總是會返回值。屬於宣告式編程的程式語言有,HTML、SQL、LINQ。
指令式編程(Imperative Paradigm)的程式碼經常使用程式語言基本的語句(statement),例如:for, while, if , switch…等等。屬於指令式編程的程式語言有,C、JAVA。
結語
函式編程(Functional Programming)誕生了五十多年後,終於獲得程式開發者大量的關注,目前 ML 非常紅的 Python 以及前後端 JavaScript 等語言,對於函式編程(Functional Programming)的支持都很強。本篇文章整理 JavaScript 符合函式編程(Functional Programming) 概念的幾個元素(First-class and higher-order functions and Pure Functions),希望透過 JavaScript 的實例理解函式編程所講述的核心理念為何。最後比較宣告式編程(Declarative Paradigm)以及指令式編程(Imperative Paradigm),對自己過去在軟體開發這塊領域所學的做個整理,理清並梳理已有的知識。