# [JavaScript] 粗淺整理 Imperative(命令式)及 Declarative(強調式)
###### tags: `前端筆記`
在看 React 的課程時老師一直強調 「React 有使用 Declarative Approach 的概念」,原本想說只講一次就算了,先會用 React 之後再補足,結果 Declarative Approach 出現太多次了,所以就花了一個晚上大略整理。
## Imperative(命令式)
我現在大多數的撰寫程式思維,主要是告訴電腦「怎麼做」(How to do)。常會使用 statement(陳述式)(比方來說 `if`, `for`, `while` 等等),陳述式的話就不會回傳(return)值。
範例:從陣列中找到需要的值
```javascript=
const manga = ['請叫我英雄', '異獸魔都', '風之谷'];
// 現在要找 異獸魔都
function findManga () {
const temp = [];
for (let i = 0; i < manga.length; i++) {
if (manga[i] === '異獸魔都') {
temp.push(manga[i]);
}
}
return temp;
}
console.log(manga()); //["異獸魔都"]
```
### 告訴電腦「怎麼做事情」
觀看上方的程式碼可以發現,我的目標是「找到異獸魔都」,但是我是告訴電腦「怎麼做事情」(用 `for loop` 跑迴圈的資料,找到我要的就 `push` 到 `temp` 裡面,都是我自己寫方法告訴電腦 how to do)。
## Declarative(強調式)
另一種程式思維方式,主要是告訴電腦「做什麼」(What to do)。較少使用 statement(陳述式),多用 expression(表達式),表達式會回傳(return)值,Functional Programming(FP)就是要用這些回傳的值(state),來當作函式的 input(也就是 argument),之後等到我學習 FP 再深入理解 FP。
以上方的例子用 Declarative(強調式)(What to do):
```javascript=
const manga = ['請叫我英雄', '異獸魔都', '風之谷'];
// 現在要找 異獸魔都
const findManga = manga.filter((item) => item === '異獸魔都');
console.log(findManga); // ["異獸魔都"]
```
### 告訴電腦「要做什麼」
與 Imperative(命令式)的著重點不同,Declarative(強調式)用了 array method 達到我要做什麼的目標,即便目標相同(找到異獸魔都),但是我不需要自己寫判斷(How to do),而是往「What」的方向思考(要篩選異獸魔都)透過 `filter` 的幫助得到我要的結果。
## 更複雜一點的例子
從陣列裡面找要的資料,但是陣列裡面的資料必須先小寫才可以尋找。
使用 Imperative(命令式):
[*ref.: Imperative vs Declarative programming in JavaScript*](https://medium.com/weekly-webtips/imperative-vs-declarative-programming-in-javascript-25511b90cdb7)
```javascript=
const myTurtles = ['Snapping Turtle', 'Sulcata Tortoise'];
const getTortoises = function () {
let tortoises = [];
for(let i = 0; i < myTurtles.length; i++) {
// 告訴電腦如何做
// 1. for loop 跑資料
// 2. 每次的 loop 判斷 arr 的 value 是否與需求相同
if(myTurtles[i].toLowerCase().includes('tortoise')) {
tortoises.push(myTurtles[i]);
}
}
return tortoises;
}
getTortoises();
// => ['Sulcata Tortoise']
```
使用 Declarative(強調式):
[*ref.: Imperative vs Declarative programming in JavaScript*](https://medium.com/weekly-webtips/imperative-vs-declarative-programming-in-javascript-25511b90cdb7)
```javascript=
const myTurtles = ['Snapping Turtle', 'Sulcata Tortoise'];
// 告訴電腦做什麼?
// 目標:找到 Sulcata Tortoise
// 1. isTortoise 判斷
// 2. getTortoise 藉由判斷得到目標
const isTortoise = (input) => input.toLowerCase().includes('tortoise');
const getTortoise = (input) => input.filter(isTortoise);
getTortoise(myTurtles);
// => ['Sulcata Tortoise']
```
### 為什麼 `const getTortoise = (input) => input.filter(isTortoise);` 還可以執行?
因為 `arr.filter` 第一個參數設定是 `callBack`,因為函式在 JavaScript 享有一級函式的地位(first-class-function),所以函式可以做任何「值」可以做的事情。
此例子是當作 Argument 來叫用 `arr.filter` 方法,所以此時 `arr.filter` 就會照著 `myTurtles` 的值跑迴圈,每次迴圈都會查看 `callBack`(也就是 `isTortoise`,指向的記憶體為一個箭頭函式)是否為 `true`,如果是 `true` 的話就會保存起來。
### 那麼為什麼 `isTortoise` 會自動接到 `arr.filter` loop 的 value 當作叫用函式的 Argument?
道理就和 `addEventListener` 寫 `callBack EventHandler` 一樣,因為如果加了括號()就會叫用函式,所以寫成 `callBack` 就會自動接收 Argument。
```javascript=
const myTurtles = ['Snapping Turtle', 'Sulcata Tortoise'];
const isTortoise = (input) => input.toLowerCase().includes('tortoise');
const getTortoise = (input) => input.filter(isTortoise);
// arr.filter((value) => value === 1);
// arr.filer 是接收 callBack(Argument)叫用的
// 這裡就可以想成
// myTurtles.filter((value) => value.toLowerCase().includes('tortoise'))
// 只是這樣子太難理解了,用 function 達到「具體化」的命名,提升程式碼的閱讀性
getTortoise(myTurtles);
// => ['Sulcata Tortoise']
```
## 為什麼 React 有用 Declarative(強調式)的概念?

[*ref.: Declarative programming - Fun Fun Function*](https://www.youtube.com/watch?v=yGh0bjzj4IQ)
因為 React 是透過 state 的轉換達到頁面(view)更新的效果,切記心法:
> State change only happens from an action and views are only updated from state changes.
> 由一個指令(或動作)更動 state,state 更動後再更動 view。
其實 React 更新畫面前還有用 Virtual Dom 與現在真實的 DOM 比對哪裡不同,之後「只更新不同的部分」。在這段尋找不同的時間點間就是運用 Declarative(強調式)的概念得到(return)state 與真實的 DOM 比對,加上更多厲害的函式確保只更新不同的地方,達到降低耗能的目標。
## 總結
我一開始都覺得兩個都是可以達到目標的方法,怎麼樣才是「How」跟「What」的不同?直到我看了一些範例才對「What to do」跟「How to do」的差別有一點點的理解(自己寫方式告訴電腦做什麼達到目標 / 著重做什麼才可以達到目標)。現在寫程式碼時就要讓自己漸漸思考「What」>「How」、要更多用 `arr.method` 與 `obj.method` 以及用三元判斷取代 `if` ==取得值==,因為這個觀念對我之後想要學習的 FP 有很大的關聯性。
## 參考資料
1. [Declarative programming - Fun Fun Function](https://www.youtube.com/watch?v=yGh0bjzj4IQ)
2. [Imperative vs Declarative programming in JavaScript](https://medium.com/weekly-webtips/imperative-vs-declarative-programming-in-javascript-25511b90cdb7)
3. [Buzz Word 1 : Declarative vs. Imperative](https://ithelp.ithome.com.tw/articles/10233761)
4. [React - The Complete Guide (incl Hooks, React Router, Redux), 32](https://www.udemy.com/course/react-the-complete-guide-incl-redux/learn/lecture/25595416)