柯里化标准代码
function curry(fn , decided_args=fn.length){//length是函数对象的一个属性值,指该函数有多少个必须传入的参数,那些已定义了默认值不算在内
return (function prevSet(preArg){
return function curried(laterArgs){
var args = preArg.concat(laterArgs);//将laterArgs放在args里,作为fn的实参数组
if(args.length>decide_args)//如果参数够了,则执行fn
return fn(...args)
else
return prevSet(args);
//将args值放入preArgs中
//再次循环将新输入的值放入args中 args = prevArgs.concat(laterArgs)
//当长度什么时候够了,就将args数组解构,输入进fn中
}
}([]))//立即执行函数,传入空数组作为preArg的初始参数
}复制代码
partial 标准代码
function partial(fn,...presetArgs){//函数和初始化值必须一起传入
return function partiallyApplied(...laterArgs){
return fn(...presetArgs,..laterArgs)
}
}复制代码
curry和partial区别
如下方这么写两个是没有区别
var add=(presetArgs,laterArgs)=> presetArgs+laterArgs
//partial
var example = partial(add,3);
example(3)//6 example = add(3,item)
//curry
var example2 = curry(add)(3)//add 传入fn 3传入preArg
example2(3)复制代码
但如果3是个未知数,需要后续传入实现呢,比如这样
var adder =curry(add)
//从某处不知名的地方,取了个值放入了laterArg中
[1,2,3,4].map(adder(laterArg)); 复制代码
对于多参传入,curry比partial 好用很多
function sum(...nums) {
var total = 0;
for (let num of nums) {
total += num;
}
return total;
}
sum( 1, 2, 3, 4, 5 ); // 15
// now with currying:
// (5 to indicate how many we should wait for)
var curriedSum = curry( sum, 5 );//限制传入参数为5个
curriedSum( 1 )( 2 )( 3 )( 4 )( 5 ); // 15
复制代码
看一下原句说的优点:
The advantage of currying here is that each call to pass in an argument produces another function that's more specialized
这里说的传入一个参数,返回一个新的函数的意思是通过preArg改变了curried函数 args里面的缓存的内容,这个返回的新的函数可以在程序中获取和调用,相比较于partial呢,parital只是一股脑的将参数传递进去,并且得到结果
emmm,形象化的理解的话,就和我画的这张图一样,两个厨师,一个是我,一个是米其林大厨