知足如下兩點的函數:javascript
叫高階函數,很顯然js中的函數知足高階函數的條件。java
函數做爲參數:git
function pow(x) { return x * x; } const arr = [1, 2, 3]; const res = arr.map(pow);
函數做爲返回值:github
function getPrintFn() { function print(msg) { console.log(msg); } return print; }
高階函數與函數式編程有什麼關係?經過上一篇咱們知道函數式編程採用純函數,那怎麼把不純的函數轉化爲一個純函數呢?經過把不純的操做包裝到一個函數中,再返回這個函數(即上面的例子),便可達到目的。編程
只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數。
特色:
接收單一參數,將更多的參數經過回調函數來搞定;
返回一個新函數,用於處理全部的想要傳入的參數;
須要利用call/apply與arguments對象收集參數;
返回的這個函數正是用來處理收集起來的參數;數組
function add(x, y) { return x + y; } // 柯里化 function add(x) { return function(y) { return x + y; } } const increment = add(1); increment(2); // 3
當咱們談論純函數的時候,咱們說它們接受一個輸入返回一個輸出。curry 函數所作的正是這樣:每傳遞一個參數調用函數,就返回一個新函數處理剩餘的參數。這就是一個輸入對應一個輸出。curry函數適用於如下場景:網絡
在函數式編程中,經過將一個個功能單一的純函數組合起來實現一個複雜的功能,就像樂高拼積木同樣,這種稱爲函數組合(代碼組合)。下面看一個例子:app
最佳實踐是讓組合可重用。異步
咱們知道,函數式編程實質是經過管道把數據在一系列純函數間傳遞,可是,控制流(control flow)、異常處理(error handling)、異步操做(asynchronous actions)和狀態(state)呢?還有更棘手的反作用(effects)呢?這些問題的解決就要引入函子的概念了。async
咱們首先定義一個容器,用來封裝數據
函子封裝了數據和對數據的操做,functor 是實現了map函數並遵照一些特定規則的容器類型。
把值裝進一個容器,並且只能使用 map 來處理它,這麼作的理由究竟是什麼呢?
讓容器本身去運用函數能給咱們帶來什麼好處?
Functor 是一個對於函數調用的抽象,咱們賦予容器本身去調用函數的能力。當 map 一個函數時,咱們讓容器本身來運行這個函數,這樣容器就能夠自由地選擇什麼時候何地如何操做這個函數,以至於擁有惰性求值、錯誤處理、異步調用等等很是牛掰的特性。
1.Maybe(處理null問題)
2.Either(if…else)
3.IO(IO、網絡請求、DOM)
4.Monad(嵌套問題)
一種用來處理null和undefined問題的函子,避免繁瑣的手動判空操做
一種用來處理if…else問題的函子
經過返回一個獲取數據的函數來延遲IO的反作用,等調用者去執行有反作用的函數,
以保證獲取數據過程當中的無反作用特性
monad 是能夠變扁(flatten)的實現了of方法的 functor
學習函數式編程,實際上就是學習函子的各類運算。因爲能夠把運算方法封裝在函子裏面,因此又衍生出各類不一樣類型的函子,有多少種運算,就有多少種函子。函數式編程就變成了運用不一樣的函子,解決實際問題。
參考文檔
https://github.com/xitu/gold-...
https://llh911001.gitbooks.io...