# React 大小事之 Functional Programming
<H3>Functional Programming 是什麼? (簡稱 FP)</H3>
1. 什麼是functional programming ?
基本上 Functional Programming 就是
* Style / Pattern 一種撰寫風格
* Paradigm 一種規範
* Mindset 抽象式思維
所以 FP 不是一種 “程式語言”,也與框架無關,以 JS 來說,不管你是用 Vue、React、Angular、原生 JS 都是可以用 FP 思維去撰寫的。
2. 為何要學? 舊思維不好在哪
* 無法執行 DRY / 很難共用
* 系統難以維護與測試
* 難以閱讀
大家可能都有遇過,小案子寫起來很順沒有什麼太大問題,但當系統越變越複雜,就會發現難以維護、執行 DRY (Don't Repeat Yourself) 很困難、總是花很多時間 debug、不知道怎麼寫測試,甚至出現越改越糟的狀態。
FP 使用大量的 Function,幾乎每個 Function 都可以由更小的 Function 組合出來,好處是可以減少程式碼的重複,所以 FP 的寫法通常比較簡短跟容易。
<h5>FP 精華就是會盡量抽象化 (抽象化時命名很重要,最好是一看函式名稱就知道在做什麼)</h5>
總而言之 FP 就是輕量化程式碼而且容易理解、改變、除錯和具有彈性
<h3>Functional Programming 的使用 </h3>
JavaScript 框架就是使用FP來開發程式,因此若想學習 React.js 勢必也要熟悉FP的基本概念,而 JavaScript 程式語言也需要符合FP的編程理念。
了解以下的方法可讓我們更方便開發!!
* First-class and higher-order functions
* Pure Functions
* Declarative vs Imperative
<h4>1. First-class and higher-order functions</h4>
First-class(一等公民) — 我們可以想像成對待函式(Functions)如同對待其他資料型別一樣。
For example:const a = 1,1 的值也就指定給 a
因此我們也可以直接將函式(Functions)指定給任一變數
For example:const a = (x,y) => x * y,a 也就變成(x * y) Function 的變數,呼叫 a(2, 4) 則會返回值8。
Higher-order functions(高階函式)至少會滿足下列其中一項條件
數學(高階函式)是指至少會滿足下列一項條件的函數
* 接受一個或多個函數作為輸入
* 輸出一個函數
在 FP 的使用上是指
* 可以將函式(至少一個)當成參數傳入另一個函式。
* 可以將函式當成另一個函式的回傳值。
Code example :
```
const add = function(x){ //add函式接收參數並且回傳一個 Function 作為回傳值
return function(y){
return x + y;
};
};
const addFive = add(5);
const addTen = add(10);
addFive(2) // ans : 7
addTen(2) // ans : 12
```
從上述範例我們可以得知,add函式接收參數 (x) 並且回傳一個函式 ( x + y ) 作為回傳值。因此在宣告addFive 變數時,同時給定 x=5 至 add 函式,往後使用 addFive 變數(函式變數)皆會從 5 開始加減。
<h4>2. Pure Functions (純函式)</h4>
Pure Functions 意指將相同的input丟入函式,永遠會回傳相同的output結果,而且在過程中完全沒有任何的"副作用"。
<h6>" 副作用 ": 通常意味著「避免狀態改變」、「避免資料改變」,我們可以想成不與函式區塊域(block)以外的變數做互動(最典型的例子,修改全域變數的值),或者不論函式以外做了什麼,函式(Functions)內的運算依舊不受改變。</h6>
以JavaScript為例, 副作用有:
* 更改外部變數或者物件屬性(例如:全域變數、父類別範圍內的變數等)
* 寫入console.log、檔案
* 觸發外部流程
* 呼叫任何有副作用的函式(Functions)
也就是說 Pure Functions擅於純運算,而不做其他事情(例如:讀取外部資料)。
在 FP中,slice 函式(Functions)就符合我們Pure Functions的規範,相同input,永遠回傳相同output且無副作用。而splice函式(Functions)則是每次呼叫,output以及原始資料皆會不相同,因此不算是Pure Functions。
Code example :
```
// slice: Pure Function
const arr = [1, 2, 3, 4, 5, 6];
arr.slice(0, 3); // output = [1, 2, 3], arr = [1, 2, 3, 4, 5, 6]
arr.slice(0, 3); // output = [1, 2, 3], arr = [1, 2, 3, 4, 5, 6]
// splice: not Pure Function
const arr = [1, 2, 3, 4, 5, 6];
arr.splice(0, 3); // output = [1, 2, 3], arr = [4, 5, 6]
arr.splice(0, 3); // output = [4, 5, 6], arr = []
```
<h5>溫馨小提示 :
arr.splice(要插入或刪除的索引位置, 要刪除的元素數量, 要插入的元素內容)
arr.slice( begin(起始為 0)從index開始提取拷貝 , end索引值之前停止提取 )</h5>
<h4>3. Declarative vs Imperative (宣告式編程)</h4>
* Declarative Paradigm (宣告式編程)一 較為抽象的程式碼,可以藉由自然語言直觀的理解該行程式碼想要達到什麼樣的結果。描述該在哪做什麼(what to do)以及資料流程(data flow)。
然而宣告式編程較依賴表達式(expression),表達式是一個單純的運算過程,並且總是會返回值。屬於宣告式編程的程式語言有,HTML、SQL、LINQ。
* Imperative Paradigm (指令式編程) 一 程式碼具體表達需要做什麼來達到目標。描述該做什麼(how to do)以及流程控制(flow control)。
而指令式編程的程式碼經常使用程式語言基本的語句(statement),例如:for, while, if , switch…等等。屬於指令式編程的程式語言有,C、JAVA。
Code example :
```
const a = [1, 2, 3, 4, 5];
// Declarative Programming
declarativeSquare = (arr) => arr.map((val) => val*val)
declarativeSquare(a); // [1, 4, 9, 16, 25]
// Imperative Programming
imperativeSquare = (arr) => {
for (var i = 0; i < arr.length; i++) {
arr[i] *= arr[i];
}
return arr;
}
imperativeSquare(a); // [1, 4, 9, 16, 25]
```
<h3>Source:</h3>
Functional Programming 是什麼:https://ithelp.ithome.com.tw/articles/10233399
Functional Programming 的使用:https://totoroliu.medium.com/javascript-functional-programming-%E5%87%BD%E5%BC%8F%E7%B7%A8%E7%A8%8B%E6%A6%82%E5%BF%B5-e8f4e778fc08
splice:https://ithelp.ithome.com.tw/articles/10225345
slice:https://ithelp.ithome.com.tw/articles/10224915