看了不少大佬的文章,终于对柯里化有了初步的理解,简单总结一下。
什么是柯里化?
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
看了概念还是一头雾水,用代码解释一下。
例如有一个简单的加法运算:
function add(a,b,c){
return a+b+c
}
add(1,2,3); //这是接受多个参数的函数
现在把它变换成接受单一参数的柯里化函数
function add(a){
return function(b){
return function(c){
return a+b+c
}
}
}
add(1)(2)(3); //接受单一参数
柯里化函数结合了闭包的用法,不了解闭包的先学习闭包噢
柯里化把简单的问题复杂化了,同时把复杂的问题自由化了,来看这么一个例子:
// 实现一个add方法,使计算结果能够满足如下预期:
function add() {
let args = [...arguments];
function _add() {
args = args.concat([...arguments]);
return _add;
}
_add.toString = function() {
return args.reduce((pre, cur) => {
return pre + cur;
})
}
return _add;
}
add(1)(2)(3); //f 6
add(1, 2, 3)(4); //f 10
add(1)(2)(3)(4,5) ; //f 15
add(1)(2)(3).toString(); //6
函数有些难理解,建议debugger在浏览器看运行步骤。
柯里化的应用场景
手机号、邮箱的验证,我们一般会写一个通用的函数,将用于验证的正则和将要被验证的字符串作为参数传入。
function check(reg,targetString){
return reg.test(targetString);
}
这样使用会有点冗余,每次都要重复写正则表达式
check(/^1[34578]\d{9}$/, '14900000088');
check(/^1[34578]\d{9}$/, '13714357188');
check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'test@163.com');
check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, '123478@163.com');
柯里化函数的运行过程其实是一个参数的收集过程,我们将每一次传入的参数收集起来,并在最里层处理,所以可以借助这个思路来封装一下。
function createCurry(func, args) {
var arity = func.length; //2 check函数形参的长度
var args = args || [];
return function() {
var newArgs = [].slice.call(arguments);
[].push.apply(newArgs, args); //args参数push进newArgs
// 如果参数个数小于最初的func.length,则递归调用,继续收集参数
if (newArgs .length < arity) {
return createCurry.call(this, func, newArgs);
}
// 参数收集完毕,则执行func
return func.apply(this, newArgs );
}
}
var checkPhone = createCurry(check)(/^1[34578]\d{9}$/);
var checkEmail = createCurry(check)(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
最后调用就会更加简洁了。
checkPhone('14900000088');
checkPhone('13714357188');
checkEmail('xxxxx@test.com');
参考资料:https://www.jianshu.com/p/5e1899fe7d6b