函数柯里化及经典案例
先解释什么是柯里化,currying,把接收多个参数的函数变为接收单一单一参数的函数,并且返回接收剩余参数而且返回结果的新函数。
前因
我接收到柯里化是因为一次面试,题干是这样的
let a=add(1)(1)(3)()
要求实现这个函数让里面的参数能到递加得到结果
const add=(a)=>{
let current=a;
let adder=function(b:any){
if(b){
current=current+b;
return adder;
}
return current;
}
return adder;
}
这其实就是函数柯里化,有利用闭包,保持了current变量的在一段时间内的驻留内存,从而达到函数连续调用并计算出最后的结果值。
// 每个参数可传递多个参数。
function curry(...arg:any[]){
let args=arg;
let adder= function(...arg:any[]){
args.push(...arg);
return adder;
}
adder.toString = function () {
return args.reduce(function (a:number, b:number) {
return a + b;
});
}
return adder;
}
lodash-curry柯里化函数
lodash-curry柯里化的核心代码。我认为没有问题。
function createCurry(func, bitmask, arity) {
var Ctor = createCtor(func);
function wrapper() {
var length = arguments.length,
args = Array(length),// args 持久保留的数据
index = length,
placeholder = getHolder(wrapper);
while (index--) {
args[index] = arguments[index];
}
var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
? []
: replaceHolders(args, placeholder);
length -= holders.length;
// 看剩下的参数
// arity 参数的数量,
// 用于确定需要继续递几次
if (length < arity) {
return createRecurry(
func, bitmask, createHybrid, wrapper.placeholder, undefined,
args, holders, undefined, undefined, arity - length);
}
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
// 执行最后得到的结果,用于返回
return apply(fn, this, args);
}
//
return wrapper;
}
从lodash的实现来看,柯里化主要运用了闭包,用来保持我们的参数数据,然后用递归来接收接下来的函数调用。最后返回。
可应用场景
减少重复传递不变的部分参数
function simpleURL(protocol, domain, path) {
return protocol + "://" + domain + "/" + path;
}
let myURL1 = _.curry(simpleURL)('https', 'mysite');
let res1 = myURL1('home.html'); //
console.log(res1);//https://mysite/home.html
let myURL2 = _.curry(simpleURL)('http', 'mysite');
let res2 = myURL2('aboutme.html'); //
console.log(res2);//http://mysite/aboutme.html
柯里化的callback传递给map,filter等函数
var getProp = _.curry(function (key, obj) {
return obj[key]
});
var names = persons.map(getProp('name'))