函数柯里化
柯里化可以理解为:只传递给函数一部分参数来调用它,让它返回一个函数去接着处理剩下的参数。比如下面这个简单的例子:
// 实现一个add方法,满足如下需求
// console.log(add(2, 5).valueOf()); // 7
// console.log(add(2)(5).valueOf()); // 7
// console.log(add()(2, 5).valueOf()); // 7
// console.log(add()(2)(5).valueOf()); // 7
function add(...args1) {
let args = args1;
let _add = function (...args2) {
args = args.concat(args2);
return _add;
};
_add.valueOf = function () {
let result = args.reduce((pre, cur) => {
return cur + pre;
}, 0);
return result;
};
return _add;
}
一般函数都是有固定参数数量的,我们可以实现一个通用的工具函数将其柯里化
function currying(fn) {
return function curried(...args) {
// 参数已凑够(fn.length 为形参个数),直接执行
if (args.length >= fn.length) {
return fn.apply(this, args);
}
// 否则返回新函数继续收集参数(不复用外层数组,避免多次调用相互污染)
return (...next) => curried.apply(this, [...args, ...next]);
};
}
function add(x, y, z) {
return x + y + z;
}
const curryAdd = currying(add);
curryAdd(1, 2)(3); // 6
curryAdd(1)(2)(3); // 6
curryAdd(1, 2, 3); // 6
旧版本用闭包共享的
_args收集参数,导致同一个curryAdd被多次调用时参数会相互累加污染。上面的版本每次都基于已有参数生成新数组,互不影响。