//柯里化函数
//fn.length默认为函数形参的个数
function curry(fn, len = fn.length) {
return _curry.call(this, fn, len);
}
function _curry(fn, len, ...args) {
//curry后返回一个函数,闭包保存原函数fn,需要的参数个数len,已传入的参数
//返回的函数执行后 加入新传入的参数 判断是否满足执行条件 满足则运行原函数 否则重复上一步
return function (...params) {
var _args = [...args, ...params];
if (_args.length >= len) {
return fn.call(this, ..._args);
} else {
return _curry.call(this, fn, len, ..._args);
}
};
}
function sum(a, b, c, d, e, f, g) {
console.log(a, b, c, d, e, f, g);
}
curry(sum)(1)(2, 3)(4)(5, 6, 7);
//占位符柯里化
function curry(fn, length = fn.length, holder = curry) {
return _curry.call(this, fn, length, holder);
}
function _curry(fn, len, holder, args = [], holders = []) {
return function (...params) {
var _args = [...args];
var _holders = [...holders];
params.forEach(function (p) {
//当前传入的参数不是占位符
if (p !== holder) {
//上一轮还有未替换的占位符 则替换
if (holders.length) {
//获取上一轮还未替换的占位符位置
var index = holders.shift();
//在本轮记录的占位符中 删除替换的占位符 为什么不直接删除第一个元素而要查找位置呢? 因为有可能上一轮的占位符在本轮中再次被占位
_holders.splice(_holders.indexOf(index), 1);
//替换占位符的值
_args[index] = p;
} else {
//否则只要添加当前参数
_args.push(p);
}
} else {
//当前传入的参数是占位符
if (holders.length) {
//还存在上一轮未替换的占位符,则需要再次占用该位置,此时该占用属于本轮占用,从上一轮holders中删除即可 本轮的_holders中仍保留着该占位符
holders.shift();
} else {
//上一轮的占位符已经全部替换时 直接记录占位符
_args.push(p);
_holders.push(_args.length - 1);
}
}
});
if (_args.length >= len && _args.slice(0, len).every((p) => p !== holder)) {
return fn.call(this, ..._args);
} else {
return _curry.call(this, fn, len, holder, _args, _holders);
}
};
}
function sum(a, b, c, d, e, f, g) {
console.log(a, b, c, d, e, f, g);
}
curry(sum)(1)(curry, curry, 4)(curry, 3)(2, 5, 6, 7);
网友评论