柯里化与逆柯里化
1. 柯里化(Currying)
定义:柯里化是将一个多参数函数转换为单参数函数链式调用的过程,其特点是每个函数只接收一个参数,并返回接收下一个参数的函数,直到所有参数收集完毕后执行原函数。
代码示例
javascript
// 普通加法函数
function add(a, b, c) {
return a + b + c;
}
// 柯里化后的加法函数
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
console.log(curriedAdd(1)(2)(3)); // 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
自动柯里化函数实现
javascript
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...nextArgs) {
return curried.apply(this, args.concat(nextArgs));
};
}
};
}
const curriedSum = curry((a, b, c) => a + b + c);
console.log(curriedSum(1)(2)(3)); // 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
应用场景
- 参数复用:固定部分参数生成专用函数。javascript
const addTen = curriedSum(10); console.log(addTen(20)(30)); // 60
1
2 - 延迟执行:按需传入参数,灵活组合函数。
- 函数式编程:适配函数组合(如
compose
、pipe
)。
2. 逆柯里化(Uncurrying)
定义:逆柯里化是将一个依赖于对象调用的方法转换为独立函数的过程,使其接收目标对象作为参数。核心是泛化方法的使用范围。
代码示例
javascript
// 对象的push方法(依赖 Array 对象调用)
const obj = { 0: 'a', length: 1 };
Array.prototype.push.uncurried = function() {
return Array.prototype.push.apply(arguments[0], [].slice.call(arguments, 1));
};
const uncurriedPush = Array.prototype.push.uncurried;
uncurriedPush(obj, 'b');
console.log(obj); // {0: 'a', 1: 'b', length: 2}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
通用逆柯里化函数实现
javascript
Function.prototype.uncurry = function() {
const fn = this;
return function(context, ...args) {
return fn.apply(context, args);
};
};
// 逆柯里化Array的push方法
const push = Array.prototype.push.uncurry();
const array = [];
push(array, 1, 2);
console.log(array); // [1, 2]
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
应用场景
- 借用其他对象方法:例如让类数组对象使用数组方法。javascript
const slice = Array.prototype.slice.uncurry(); const args = { 0: 'a', 1: 'b', length: 2 }; console.log(slice(args, 0)); // ['a', 'b']
1
2
3 - 统一处理不同对象的方法:如统一调用不同类的
toString
方法。 - 兼容鸭子类型(Duck Typing):对不严格符合接口的对象也能操作。
核心区别
特性 | 柯里化 | 逆柯里化 |
---|---|---|
目的 | 分步传递参数,生成函数链 | 泛化对象方法,使之以函数形式调用 |
应用方向 | 多参数函数 → 单参数函数链 | 对象方法 → 独立函数 |
典型场景 | 函数组合、参数复用 | 方法借用、跨对象操作 |
总结
- 柯里化:提升函数灵活性与复用性,适配高阶函数场景。
- 逆柯里化:打破对象方法的调用限制,便于跨类型操作。
两者各有所长,柯里化更偏向函数式编程范式,逆柯里化则解决 JavaScript 原型方法的通用性问题。