# add(1)(2)(3)
# 红宝书第三版的函数柯里化
function curry(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(null, finalArgs);
};
}
这个版本的 curry 函数主要是用于创建已经设置好了一个或多个参数的函数。它的使用方式比较有限,是这样的:
function add(a, b) {
return a + b;
}
var curryAdd1 = curry(add, 1);
console.log(curryAdd1(2)); // 3
var curryAdd2 = curry(add, 1, 2);
console.log(curryAdd2()); // 3
如果要实现add(1)(2)(3)
,还需要继续改造。
# 实现 add(1)(2)(3)
// 最简单的实现,只支持固定的调用方式
const add = x => y => z => x + y + z;
add(1)(2)(3); // 6
// 升级版,支持更灵活的调用
// add(1, 2, 3);
// add(1, 2)(3);
// add(1)(2, 3);
const curry = function(fn) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length >= fn.length) {
return fn.apply(null, args);
} else {
return function() {
var innerArgs = Array.prototype.slice.call(arguments);
return curry(fn, ...args, ...innerArgs);
};
}
};
function add(a, b, c) {
return a + b + c;
}
const curryAdd = curry(add);
console.log(curryAdd(1, 2, 3));
console.log(curryAdd(1)(2)(3));
console.log(curryAdd(1, 2)(3));
console.log(curryAdd(1)(2, 3));
// 考虑以下调用方式改如何实现
// curryAdd(1, 2, 3);
// curryAdd(1)(2)(3);
// curryAdd(1, 2)(3);
// curryAdd(1)(2, 3);
这个版本相对灵活一点,支持更多的调用方式。 下面再写一个支持任意参数的链式调用的方式。
# 链式调用
function argsSum(args) {
return args.reduce((pre, cur) => {
return pre + cur;
});
}
function add(...args1) {
let sum1 = argsSum(args1);
let fn = function(...args2) {
let sum2 = argsSum(args2);
return add(sum1 + sum2);
};
fn.toString = function() {
return sum1;
};
return fn;
}
add(1); // 1
add(1)(2); // 3
add(1)(2)(1)(2)(1)(2)(1)(2); // 12
function curry(fn) {
const totalArgsNum = fn.length;
let allArgs = [];
function newFn(...args) {
allArgs = allArgs.concat(args);
if (allArgs.length >= totalArgsNum) {
const args = allArgs.slice(0, totalArgsNum);
fn(...args);
allArgs = [];
return newFn;
} else {
return newFn;
}
}
return newFn;
}
const sum = curry(function _sum(a, b, c) {
console.log(a + b + c);
});
sum(1)(2)(3); // 6
sum(1, 2)(3); // 6
sum(1)(2, 3); // 6
sum(1, 2, 3); // 6
sum(1, 2, 3, 4); // 6
← promiseA+ Scheduler 类 →