深色模式
currying 柯里化函数
背景
假设我们实现一个加法计算器,函数式
sum(a,b,c,d)
, 我们的参数不是一次获取,我们这样执行sum(1)(2,3)(4)
,我们如何处理呢?有个验证正则的函数
checkByRegExp(regex, str)
, 当我们验证邮箱是使用checkByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/,"liu@aliyun.com")
, 当我们验证手机号是使用checkByRegExp(/^1\d{10}$/, '123456')
, 如果我们如下使用
js
let curriedCheck = curry(checkByRegExp);
let checkPhone = curriedCheck(/^1\d{10}$/);
let checkEmail = curriedCheck(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
checkPhone(1234455);
checkPhone(1234456);
checkPhone(1234457);
checkEmail('a@aliyun.com');
checkEmail('a@aliyun.com');
checkEmail('a@aliyun.com');
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
这样代码复杂了,但是结构更清晰。
实现原理
柯里化函数接收参数并不马上执行,而是返回一个新的函数,这个函数可以继续接收参数,直到执行条件满足,执行函数。
可以看到柯里化函数需要将接收到的参数缓存起来。
实现代码
说明: curry 每次接收参数,则返回一个新的函数,并将参数缓存传递给下一个函数,直到满足执行条件,我们取接收参数长度 >= 原函数形参长度执行原函数
js
function curry(fn) {
// 返回一个函数,用来存储参数,当参数数目正确是,执行函数
return function _curryed(...args) {
// 当接收到的参数长度 >= 原函数的参数长度时,执行原函数
if (args.length >= fn.length) {
return fn.apply(this, args);
}
// 当接收参数不足时,返回一个新的函数用来接收参数
return function (...args2) {
return _curryed.apply(this, args.concat(args2));
};
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
示例
js
function sum(a, b, c, d) {
return a + b + c + d;
}
const curryedSum = curry(sum);
// 参数不足,不执行
console.log(curryedSum(1, 2));
// 参数不足,不执行
console.log(curryedSum(1, 2, 3));
// 参数不足,不执行
console.log(curryedSum(1)(2)(3));
// 执行
console.log(curryedSum(1, 2, 3, 4));
// 执行
console.log(curryedSum(1)(2, 3)(4));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
参考
- JavaScript 设计模式与开发实践
- 柯里化|javascript.info
- 「前端进阶」彻底弄懂函数柯里化|掘金