# [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(強調式)的概念? ![](https://i.imgur.com/vTQ9LyS.jpg) [*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)