高阶函数是至少知足下面一个条件的函数:
一、接收一个或多个函数做为参数。好比filter
函数
二、返回一个函数。 好比bind
函数
举个例子:好比咱们要筛数组[1,2,3,4,5]
中大于3的全部元素,咱们一般的实现方法为:编程
let newArr = []; for(let i = 0,len = arr.length; i < len; i++){ arr[i] > 3 && newArr.push(arr[i]) }
而使用数组filter
方法的话,只须要 let newArr = arr.filter((item) => {return item > 3})
。固然咱们也能够经过高阶函数来本身实现:api
Array.prototype.myFilter = function (fn){ let newArr = []; for(let i = 0,len = this.length; i < len; i++){ fn(this[i]) && newArr.push(this[i]) } return newArr; } [1,2,3,4,5].myFilter((item) => { return item > 3})
咱们能够经过封装高阶函数来复用和简化咱们的代码。数组
柯里化是将一个多参数的函数转换成多个单参数的函数,这个函数会返回一个函数去处理下一个参数。也就是把fn(a,b,c)
转换为newFn(a)(b)(c)
这种形象。柯里化常见的应用有:参数复用、延迟计算。好比咱们有个拼接接口地址的函数:app
function getUrl(service,context,api){ return service + context + api; } let loginUrl = getUrl('http://localhost:8080/','auth','/login') let logoutUrl = getUrl('http://localhost:8080/','auth','/logout')
每次前两个参数的值都是同样,咱们能够柯里化来封装下来达到参数复用:函数
function curry(fn){ let args = Array.prototype.slice.call(arguments,1); return function(){ let innerArgs = Array.prototype.slice.call(arguments); let finalArgs = args.concat(innerArgs); if(finalArgs.length < fn.length){ //fn.length为函数的参数个数 return curry.call(this,fn,...finalArgs) }else{ return fn.apply(null,finalArgs) } } } var getAuthUrl = curry(getUrl,'http://localhost:8080/','auth'); let loginUrl = getAuthUrl('/login') let logoutUrl = getAuthUrl('/logout')
组合函数相似于管道,多个函数的执行时,上一个函数的返回值会自动传入到第二个参数继续执行。好比咱们替换一个url中的参数:this
function replaceToken(str){ return str.replace(/{token}/g,'123455') } function replaceAccount(str){ return str.replace(/{account}/g,'xuriliang') } replaceAccount(replaceToken('http://localhost/api/login?token={token}&account={account}'))
咱们能够利用这种嵌套的写法来实现,但若是嵌套过多,代码可读性就不是很好了。固然咱们也能够在一个函数里分过程实现,不过这样函数就不符合单一原则了。利用函数组合咱们能够这样写:url
function compose() { var args = arguments; var start = args.length - 1; return function() { var i = start; var result = args[start].apply(this, arguments); while (i--) result = args[i].call(this, result); return result; } } compose(replaceToken,replaceAccount)('http://localhost/api/login?token={token}&account={account}')
组合函数使得咱们可使用一些通用的函数,组合出各类复杂运算。这也是函数编程中pointfree
的概念。prototype