在解釋什么是函數式編程之前,我們先要說下什么是命令式編程,它們都屬于編程范式的一種。命令式編程其實就是一塊一塊的代碼,其中包括了我們要執行的邏輯或者判斷或者一些運算。也就是按部就班的一步一步完成我們所需要的邏輯。而函數式編程則是類似于一個函數一個函數的調用。我們來看代碼,更清晰的理解一下函數式編程與命令式編程的區別。
//這是命令式 var printArray = function (array) {for (var i = 0; i < array.length; i++) {console.log(array[i])} } printArray([1,2,3,4,5]); //函數式 var forEach = function (array,action) {for (var i = 0; i < array.length; i++) {action(array[i])} }var logItem = function (item) {console.log(item) }forEach([2,3,4,5,6],logItem)
我們先來看看上面的代碼做了什么——“遍歷數組,然后打印數組的每一項”。在命令式編程中,我們一步一步的完成了這句話。先遍歷數組,然后打印每一項元素。那么我們再來看函數式編程,我們先聲明了兩個函數,一個是遍歷數組元素的forEach(這里的action參數其實就是一個回調函數),一個是打印每一項的logItem。我們把每一步驟的需要操作的邏輯都用函數來區分開,最后再調用函數來執行運算。
在有了ES6之后,我們可以更加方便的用函數式編程范式來編寫我們的代碼,下面我們再來看一個例子。
//找出數組中元素最小的值 //代碼十分簡單,我們假設數組的第一個元素是最小的并賦值給minVal變量 //遍歷除第一項元素以外的所有數組內元素并與minVal比較,如果當前的minVal比array[i]還要大,那么就把minVal替換成array[i]; //最后返回結果 var findMinValInArray = function (array) {var minVal = array[0];for (var i = 1; i < array.length; i++) {if(minVal > array[i]) {minVal = array[i];}}return minVal; } console.log(findMinValInArray([7,8,9,5,31,2])); //那么我們其實可以更簡單的實現上面的方法,比如Math.min以及解構操作符(...) const _min = function (array) {return Math.min(...array); } console.log(_min([5,6,9,3,1])); //我們還可以用ES6的箭頭函數,讓我們的代碼更好看一些。 const min = arr => Math.min(...arr); console.log(min([2,3,9,4,8]))
上面代碼中Math.min是一個方法,返回參數中的最小值,參數可以是無限個。那么還有ES6的箭頭函數以及擴展運算符(...)。這里不做詳細的解釋,附上連接地址,大家可以更為詳細的知道什么是箭頭函數以及擴展運算符。
那么,接下來我們看看如何利用我們前面已經學過的數組方法來讓我們的代碼更加“函數式”。
//我們先看一個命令式編程的例子 var daysOfWeek = [{name:"Monday",value:1},{name:"Tuesday",value:2},{name:"Wednesday",value:7}, ] var daysOfWeekValues_ = []; for (var i = 0; i < daysOfWeek.length; i++) {daysOfWeekValues_.push(daysOfWeek[i].value); }//再來看看函數式編程的樣子 var daysOfWeekValues = daysOfWeek.map(function (day) {//這個day其實就是數組中的每一項,具體可以去我前面的文章查看map的參數return day.value; }) console.log(daysOfWeekValues);//我們還可以使用filter來過濾一個數組的值。 //比如: //命令式 var positiveNumbers_ = function (array) {var positive = [];for (var i = 0; i < array.length; i++) {if(array[i] >= 0) {positive.push(array[i]);}}return positive; } console.log(positiveNumbers_([-1,2,1,-2])); //函數式 var positiveNumbers = function (array) {return array.filter(function (num) {return num >= 0;}) }console.log(positiveNumbers([1,2,-1,-2,-5]));//我們再來看看reduce函數 //命令式 var sumValues = function (array) {var total = array[0];for (var i = 1; i < array.length; i++) {total += array[i];}return total; } console.log(sumValues([1,2,3,4,5])); //函數式 var sum_ = function (array) {return array.reduce(function (a,b) {return a + b;}) }console.log(sum_([1,2,3,4,5])) //我們還可以用ES6的方法改進一下 var sum = arr => arr.reduce((a,b) => a + b); console.log(sum([1,2,3,4,5]))
上面我們看了一些函數式編程的例子,代碼都不復雜,很容易理解。所以就沒做詳細的注釋。那么我們下面再看最后一個有趣的例子。
//我們來用命令式編程實現一個二維數組合并為一維數組的方法 var mergeArrays_ = function (arrays) {var count = arrays.length,newArray = [],k = 0;for (var i = 0; i < count; i++) {for (var j = 0; j < arrays[i].length; j++) {newArray[k++] = arrays[i][j];}}return newArray; }console.log(mergeArrays_([[1,2,3],[4,5],[6]]));//我們最后再看看函數式的寫法 var mergeArraysConcat = function (arrays) {return arrays.reduce(function (p,n) {return p.concat(n);}) }; console.log(mergeArraysConcat([[1,2,3],[4,5],[6],[7]]))//我們再來看看牛逼的方法 const mergeArrays = (...arrays) => [].concat(...arrays); console.log(mergeArrays([1,2,3],[4,5],[6],[7],[8])); //這一行代碼需要解釋下。我們來看看(...arrays)會變成什么 console.log(...[[1,2,3],[4,5],[6],[7],[8]])//一個一個單獨的數組 //然后我們再用一個空數組去合并參數中的每一個單獨的數組就可以了
到這里我們函數式編程的簡單講解就結束了,上面的內容其實不過萬分之一,希望能讓大家對代碼的編寫打開了另一扇窗戶,其實函數式編程在我們的實際工作中也是極為有用的。希望大家可以認真對待和學習,最后,附上一個可以學習函數式編程的網址:http://reactivex.io/learnrx/。這是一個外國的練習網站,只要會簡單的英語看下來應該是沒有問題的。
最后,由于本人水平有限,能力與大神仍相差甚遠,若有錯誤或不明之處,還望大家不吝賜教指正。非常感謝!