什么是柯里化函数
柯里化函数,官方一点的解释:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
这么说有些难理解,那么我们直接使用代码来看,
首先,我们写一个最简单的几个数求和的函数:
function add(a, b, c, d) {
return a + b + c + d
}
console.log(add(1, 2, 3, 4));
正常来写,就是这样,但是这么写的话,也就意味着必须一次性将参数传完,那么柯里化函数是怎么写的呢:
function add(a) {
return function(b) {
return function(c) {
return function(d) {
return a + b + c + d
}
}
}
}
console.log(add(1)(2)(3)(4)); //10
参数是一个一个传递进去,柯里化函数其实就可以理解为,如果你的函数参数传递完成,会直接执行,没有传递完成,会继续返回一个函数并且一直期待下一次调用函数时把参数传递完成,直到传完为止。
柯里化的作用
1.延迟执行
当我们传入参数的时候,有时候不需要函数执行,柯里化就能够做到接受参数但是不执行,因为它返回的是一个函数,只有当参数全部传入时,它才会给到最终结果
2.参数复用
参数复用就是在做某些验证的时候最能体现,就用正则验证数字来举例,我们一般写代码
function fn(reg, test) {
return reg.test(test)
}
console.log(fn(/\d+/g, '123')); //true
console.log(fn(/\d+/g, 'aaa')); //false
这个时候需要一直传reg这个参数,但是既然正则表达式不变,那我就不想一直传,柯里化就可以做到:
// 柯里化正则验证
function curry(reg) {
return function(test) {
return reg.test(test)
}
}
// 我们首先只传第一个参数,也就是正则表达式,返回一个新函数fn
var fn = curry(/\d+/g)
// 之后调用fn就可以了,不需要一直传reg这个参数,这就是参数复用
console.log(fn('123'));
console.log(fn('aaa'));
柯里化函数实现
下面我们就简单封装一下柯里化函数
//args不是每次传递进来的都是空数组,所以要传个形参
function curry(fn, args) {
//获取函数fn传递参数的总长度
let length = fn.length
//给个空数组存放传递进来的数值
args = args || []
return function(...test) {
//把所有的数值放入到这个数组中
let _args = [...args, ...test]
//当传递数值的长度小于总长度是,会继续返回此函数
if (_args.length < length) {
//此时this指向curry,call要改变this指向,并指向fn
return curry.call(this, fn, _args)
} else {
//长度相等就返回和
return fn.apply(this, _args)
}
}
}
就是用之前的add函数来实验一下:
function add(a, b, c, d) {
return a + b + c + d
}
var curryAdd = curry(add)
console.log(curryAdd(1)(2)(3)(4)); //10
console.log(curryAdd(1, 2)(3, 4)); //10
console.log(curryAdd(1, 2, 3)(4)); //10