在解释什么是函数式编程之前,我们先要说下什么是命令式编程,它们都属于编程范式的一种。命令式编程其实就是一块一块的代码,其中包括了我们要执行的逻辑或者判断或者一些运算。也就是按部就班的一步一步完成我们所需要的逻辑。而函数式编程则是类似于一个函数一个函数的调用。我们来看代码,更清晰的理解一下函数式编程与命令式编程的区别。
//这是命令式 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/。这是一个外国的练习网站,只要会简单的英语看下来应该是没有问题的。
最后,由于本人水平有限,能力与大神仍相差甚远,若有错误或不明之处,还望大家不吝赐教指正。非常感谢!
一只想要飞得更高的小菜鸟