javascript是一門多範式編程語言,什麼叫多範式?通俗一點來說,無論是爛大街的面向對象,仍是面向切面、函數式編程啥都能寫。函數式編程不是用函數來編程,其主旨是將複雜的函數轉化爲簡單的函數。這兩年隨着React的火熱,函數式編程的概念也開始流行起來,RxJS、cycleJS、lodashJS、underscoreJS等多種開源庫都使用了函數式的特性,可是相信絕大部分人看完有關函數式編程的書籍,仍是一臉懵逼。因此下面用我一年級的智商對函數式編程的理解,來介紹一些函數式編程的知識和概念。javascript
純函數的定義是,對於相同的輸入,永遠會獲得相同的輸出,並且沒有任何可觀察的反作用,也不依賴外部環境的狀態。java
var xs = [1,2,3,4,5]; // 純的 xs.slice(0,3); //=> [1,2,3] // 不純的,改變了原數組的值 xs.splice(0,3); //=> [1,2,3]
大多數有用的純函數都應有至少一個參數。全部有用的純函數都應該返回一些東西。數據庫
let addNoReturn = (x, y) => { let z = x+ y } //無用的純函數
如今你能夠嘗試打開瀏覽器的控制檯,執行這樣一個函數編程
let add = (x, y) => x + y add(1, 2) //3
執行一次,結果是3。
如今你能夠再次執行一次數組
add(1, 2) //3
結果仍是3,再執行一次瀏覽器
add(1, 2) //3
結果仍是3,驚不驚喜,意不意外?
再看下面一個函數緩存
let wirteFile = (x) => { localStorage.setItem('font', '1') return x; }
這個是純函數嗎,相同的結果也是相同的輸出啊?
顯然這個不是純函數,純函數不能修改任何外部變量,純函數沒有函數反作用。
反作用可能包含,但不限於:app
更改文件系統編程語言
往數據庫插入記錄函數式編程
發送一個 http 請求
打印/log
DOM 查詢
看到這裏你可能會把我拉黑,只有純函數我還怎麼寫代碼,怎麼完成需求?
在函數式編程中,你不單單編寫純函數。
函數式語言不能消除函數反作用,它們只能限制函數反作用。由於程序必須和真實世界交互,每個程序總有一些部分必須是不純的。目標是減小不純代碼的數量並將它們和咱們程序中的其餘部分隔離。
純函數不只下降了系統的複雜度,還有不少很棒的特性,好比可緩存性
const memorize = f => { const cache = {}; return function() { const arg_str = JSON.stringify(arguments); cache[arg_str] = cache[arg_str] || f.apply(f, arguments); return cache[arg_str]; }; }; const addNumber = memorize( x => x + 1) //第一次計算慢 addNumber(1) //第二次有了緩存,速度快了很多 addNumber(1)
咱們不用每次都本身實現memorize函數,lodash、ramda都提供了很好的封裝。