柯里化定义
维基百科定义
- 是把接收多个参数的函数,变成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数,而且返回结果的新函数的技术
- 柯里化声称 “如果你固定某些参数,你将得到接受余下参数的一个函数”
简单讲就是将函数的多个参数返回不同的函数执行,将多个参数进行执行拆解成单步骤执行,一个函数执行一个步骤
更简单的讲只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数
举个例子
function foo(a, b, c) {
return a + b + c;
}
//柯里化处理之后的函数
function sum(a) {
return function (b) {
return function (c) {
return a + b + c;
};
};
}
console.log(foo(10, 20, 30));
console.log(sum(10)(20)(30));
foo函数接收三个函数,利用柯里化将三个参数返回相对应的函数去执行,每个函数执行一个对参数的操作
可以将上面的柯里化处理函数简化
const sum = (a) => (b) => (c) => a + b + c;
但是在将上面的例子来看,进行柯里化之后的函数,步骤繁琐,执行效率也不高,但是为什么还要将函数进行柯里化呢,这里就涉及到设计模式相关的,有一个重要的模式就是让函数的职责单一
- 当我们在进行函数式编程,每一个函数都尽可能只处理一类或者一个问题,而不是将所有的问题交给一个函数进行处理
- 那么我们是否就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果
function sum(a) {
a = a + 2
return function (b) {
b = b * 2
return function (c) {
c = c ** 2
return a + b + c;
};
};
}
柯里化还有一个重要的使用场景是对参数复用
function log(date, type, message) {
console.log(
`[${date.getHours()}:${date.getMinutes()}]:[${type}]:[${message}]`
);
}
log(new Date(), 'debug', '参数错误');
log(new Date(), 'debug', 'not a function');
log(new Date(), 'debug', 'bad request');
以上面的例子来说,前两个参数是重复的,每次都要写同样的代码,唯一不同的是后面的message不同,如果有大量的日志需要重写,会非常麻烦,这时就可以用柯里化将参数复用
const log = (date) => (type) => (message) => {
console.log(
`[${date.getHours()}:${date.getMinutes()}]:[${type}]:[${message}]`
);
};
//时间重复
const datelog = log(new Date());
datelog('debug')('参数错误');
datelog('request')('bad request');
//时间和类型重复
const dataAndType = log(new Date())('debug');
dataAndType('参数错误');
dataAndType('not a function');
dataAndType('bad request');
通过柯里化可以将重复的参数进行复用,减少了代码的冗余
自动柯里化函数实现
上面的柯里化函数都是手动实现的,接下来用一个函数来自动实现柯里化的过程
function currying(fn) {
//传入需要处理的函数
function curryied(...args) {
//传入处理函数的参数
/**
* 1.fn(10,20,30)
* 2.fn(10)(20)(30)
* 3.fn(10,20)(30)
*/
//第一种情况
//函数调用时参数全部使用
if (args.length >= fn.length) {
return fn.apply(this, args); //直接返回当前调用的函数,并且绑定当前调用函数的this
} else {
//第二种情况
//第二种情况和第三种情况是一样的,这里是将第二种情况转换为第三种情况,在转换为第一种情况
//递归调用
//此时args是10,args2是20,
//现在是需要将传递过来的参数进行拼接,直到转变成第一种情况
function curryied2(...args2) {
return curryied.apply(this, [...args, ...args2]);
}
return curryied2;
}
}
return curryied;
}
function add(x, y, z) {
return x + y + z;
}
var curryadd = currying(add);
console.log(curryadd);
console.log(curryadd(10)(20)(30));
console.log(curryadd(10, 20, 30));
console.log(curryadd(10, 20)(30));
网友评论