大概幾個月前,受題葉影響開始關注函數式編程,在看完一本 js 的函數式以後,對函數式有了點基本的瞭解。前端
函數式給個人感受,最大的一個主旨是是編程中全部過程可控,尤爲在 js 這種沒有原則的語言中,過程可控制有爲重要。git
到底什麼是函數式,他和命令式編程和麪向對象有什麼區別。(知乎上已經有不少討論了,感興趣的話,我在結尾的地方貼了一些連接。)
總的來講,在函數式中,函數是一等公民,函數能做爲變量的值,函數能夠是另外一個函數的參數,函數能夠返回另外一個函數等等。github
函數式中有些我的感受比較有意思的點編程
最喜歡純函數了,什麼是純函數呢?純函數有三個重要的點:promise
這有什麼好處呢?當你有一堆函數對某個數據進行操做的時候,就能輕鬆定位到哪些函數出了問題,這也就是 Redux 的中心思想,控制狀態的 Reducer 就是一個純函數。函數式編程
說到純函數,不得不聊聊不可變。函數
FB 在推出 React 以後, immutable.js 也跟着火起來了。不可變,顧名思義,就是變量或者結構在定義以後不能再發生值的變更,全部操做只是產生新的值而不是去覆蓋以前的變量。這樣去控制數據,可以讓數據流動更加可控。this
在 jQuery 大行其道的代碼中,最爲人稱讚的莫過於其鏈式操做了,但不知道有沒有人跟我同樣遇到過一些問題,好比我對一個節點進行操做,搞着搞着當前節點不是這個節點了,當我須要對這個節點再進行一次操做的時候,只能新開一個鏈式。spa
在函數中,流永遠只是對當前的那個初始的數據進行操做,並且當加上惰性鏈,全部過程更加容易控制。code
什麼是惰性鏈?
回想一下 jq 的鏈式操做,是否是每次一個連接加上去就立馬生效,當你寫完一堆鏈式以後,發現不對,若是不能一眼看出是哪步錯了,只能一次次去刪最後的操做來找緣由。而惰性鏈是在你寫完鏈式時候並不會執行,而是在最後跟上一個執行用的函數,纔會去執行前面的全部函數。
打個比方,當咱們須要類型判斷的時候,紅皮書裏通常都是各類 if,不知道平時寫的時候也是這樣,用個 utils 寫各類類型判斷的函數,而後挨個 if。
用 mixins 思路的話,大概能夠這麼去作:
dispach( function(s){ return isString(s) ? s : undefined }, function(s){ return isArray(s) ? stringifyArray(s) : undefined }, function(s){ return isObject(s) ? stringfyObject(s) : undefined }, function(s){ return s.toString() } )
這樣只要有個函數返回的確定是字符串了。
響應式編程是一種面向數據流和變化傳播的編程範式,數據更新是相關聯的。好比不少時候,在寫界面的時候,咱們須要對事件作處理,伴隨着前端事件的增多,對於事件的處理愈發須要更加方便的處理。
設想一下,平時在處理事件的時候,一單上了複雜度,好比輸入的時候,須要中止輸入的時候才進行,這個時候又只能輸入長度大於2才進行事件,當仍是以前的數據的話不進行事件,能夠考慮一下這個狀況下如何去寫。
拿 RxJs 中的一端例子舉例
var keyup = Rx.Observable.fromEvent($input, 'keyup') .map(function (e) { return e.target.value; }) .filter(function (text) { return text.length > 2; }) .debounce(750) .distinctUntilChanged();
是否十分簡潔。
把函數範式裏的一套思路和響應式編程合起來就是函數響應式編程。
不知道有沒有發現其實 Promise 也是響應式編程的一種。
舉個寒冬大大的代碼,在一個按鈕上綁定兩個事件,一個是 5s 後觸發,一個是用戶點擊。
function wait(duration){ return new Promise(function(resolve, reject) { setTimeout(resolve,duration); }) } function waitFor(element,event,useCapture){ return new Promise(function(resolve, reject) { element.addEventListener(event,function listener(event){ resolve(event) this.removeEventListener(event, listener, useCapture); },useCapture) }) } var btn = document.getElementById('button'); Promise.race([wait(5000), waitFor(btn, click)]).then(function(){ console.log('run!') })
把兩個事件綁定到按鈕上,這兩個事件函數同時也是 promise,這樣只要有一個觸發了就會執行,相比普通代碼
btn.addEventListener(event, eventHandler, false); setTimeout(eventHandler, 5000); function eventHandler(){ console.log('run!'); }
當須要增長更多事件組合的時候,更加容易拓展。
剛纔的代碼,用 Rx.js 實現會更加簡潔
var btn = document.getElementById('button'); var logRun = Rx.Observable.fromEvent(btn, 'click') .merge(Rx.Observable.timer(3000)) .subscribe(e => { console.log('run!'); logRun.dispose(); // 若是是一次性的就移除observable });
先這樣,如有不對的地方請告知,感謝~