# 高阶函数
高阶函数就是输入参数里有函数,或者输出是函数的函数。
# 1.函数作为参数
如果你用过 setTimeout、setInterval、ajax 请求,那么你已经用过高阶函数了
最常看到的场景:回调函数,因为它将函数作为参数传递给另一个函数。
比如 ajax 请求中,我们通常使用回调函数来定义请求成功或者失败时的操作逻辑:
$.ajax('/request/url', function(result) {
console.log('请求成功!')
})
在 Array、Object、String 等等基本对象的原型上有很多操作方法,可以接受回调函数来方便地进行对象操作。这里举一个很常用的 Array.prototype.filter() 方法,这个方法返回一个新创建的数组,包含所有回调函数执行后返回 true 或真值的数组元素。
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']
var result = words.filter(function(word) {
return word.length > 6
}) // 输出: ["exuberant", "destruction", "present"]
回调函数还有一个应用就是钩子,如果你用过 Vue 或者 React 等框架,那么你应该对钩子很熟悉了,它的形式是这样的:
function foo(callback) {
// ... 一些操作
callback()
}
# 2.函数作为返回值
经常看到的高阶函数的场景是在一个函数内部输出另一个函数
function foo() {
return function bar() {}
}
利用闭包来保持着作用域
function add() {
var num = 0
return function(a) {
return (num = num + a)
}
}
var adder = add()
adder(1) // 输出: 1
adder(2) // 输出: 3
# 柯里化(Currying)
柯里化(Currying),又称部分求值(Partial Evaluation),是把接受多个参数的原函数变换成接受一个单一参数(原函数的第一个参数)的函数,并且返回一个新函数,新函数能够接受余下的参数,最后返回同原函数一样的结果。
核心思想是把多参数传入的函数拆成单(或部分)参数函数,内部再返回调用下一个单(或部分)参数函数,依次处理剩余的参数。
理解:处理一个参数,返回一个函数,再处理一个参数,再返回一个函数...
柯里化有 3 个常见作用:
1.参数复用 2.提前返回
function add(x) {
return function(y) {
return function(z) {
return x + y + z
}
}
}
add(1)(2)(3) // 6
// 等同于
const firstFunc = add(1) // 传入x参数
const secondFunc = firstFunc(2) // 传入y参数
secondFunc(3) // 传入z参数3,返回6
secondFunc(6) // 传入z参数3,返回9
柯里化函数是把一个有 n 个参数的函数变成只有一个参数的函数
Add = (x,y,z) => x+y+z
变成了 curryAdd = x => y => z => x+y+z
简单说,函数柯里化就是对高阶函数的降阶处理,缩小适用范围,创建一个针对性更强的函数。
# 偏函数
偏函数是创建一个调用另外一个部分(参数或变量已预制的函数)的函数,函数可以根据传入的参数来生成一个真正执行的函数。其本身不包括我们真正需要的逻辑代码,只是根据传入的参数返回其他的函数,返回的函数中才有真正的处理逻辑比如:
var isType = function(type) {
return function(obj) {
return Object.prototype.toString.call(obj) === `[object ${type}]`
}
}
var isString = isType('String')
var isFunction = isType('Function')
在 react 中高阶组件就是偏函数的一种表现形式
平时我们用的节流(throttle),防抖(debounce)也是偏函数
举个例子理解两者的区别
// 函数柯里化
const add = (a) => (b) => (c) => a + b + c
add(1)(2)(3)
// 偏函数
const add = (a) => (b, c) => a + b + c
add(1)(2, 3)