柯里化(Currying)
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术。(返回和原函数相同的结果)
来个例子
假如我们封装了一个柯里化函数,那么我们能干什么呢?
function Curry(fn){}
我现在有一个求和函数,如下
function add(a, b, c, d) {
return a+b+c+d;
}
这个柯里化函数能做到什么呢?
// 封装一个柯里化函数 期待每一次将剩余参数进行传递
var newAdd = Curry(add);
newAdd(1)(2,3)(4);
newAdd(1)(2)(3)(4);
newAdd(1,2)(3,4);
newAdd(1,2,3,4);
每一次我都可以传进任意参数,可以传进全部,也可以只传一个,直到我获得到了所有的参数为止,并且所得到结果和我正常调用的 add(1,2,3,4) 一样。
实现柯里化,我们怎么才能让这个函数在接受一个函数可以继续传参呢,在上一个函数运行结束后,返回一个函数。
众所周知,函数名后面带个括号是执行这个函数
newAdd(1)
我们传入第一个参数时去判断,本次传入的实参的个数,和原来函数形参的个数是否一样?怎么判断呢?
函数的length属性可以获取,形参个数。
获取实参个数的话,就用arguments.length 因为arguments是个实参有映射关系的
如果传入实参个数不够那么就要返回一个函数,获取新的实参
所以最后的函数如下,我会把每一段重要的都注释,很简单。
function Curry(fn) {
// 通过length属性去获取函数形参的个数
var lon = fn.length;
// 用于计算你实参的个数
var num = 0;
//创建一个数组,用来保存每次实参的值
var arr = [];
//返回一个函数,因为是闭包所以上面的值都不会出现重置的情况,不需要形参
//(因为你不知道他会传入几个实参),通过arguments获取
return function kl() {
//遍历,把每次传入的实参,放入数组中
for (var i = 0; i < arguments.length; i++) {
arr[num] = arguments[i];
num++;
}
//只要现在已有的实参个数不等于原函数形参个数,就返回这个函数,继续去获取实参
if (num<lon) {
return kl;
} else {
//否则的话就把num清零方便下一个调用
num=0;
//当实参数和形参数相等时执行函数,使用的apply,因为所有的实参都存在数组里
return fn.apply(this,arr);
}
}
}
上面就是我思考的柯里化函数,那来验证一下吧
// 四个参数
var newAdd = Curry(add);
function add(a, b, c, d) {
return a+b+c+d;
}
console.log(newAdd(1)(3)(2)(4));
console.log(newAdd(1,2)(3,4));
console.log(newAdd(1)(2,3)(4));
// 六个参数
var newBdd = Curry(bdd);
function bdd(a, b, c, d, e, f) {
return a+b+c+d+e+f;
}
console.log(newBdd(1,2)(3,4)(5)(6));
console.log(newBdd(1,2,3,4,5,6));
成功的达到了想要的效果。
(如果这篇文章有什么问题请及时联系我!)