定义
在计算机科学中,柯里化把接受多个参数的函数编程变为接受一个单一的参数(最初函数的第一个参数)的函数,并且返回接收余下的参数且返回结果的新函数的技术(缩小适用范围,创建一个针对性更强的函数)。
test(1, 2, 3);
test(1)(2)(3);
test(1, 2)(3);
test(1)(2, 3);
柯里化后,在未收够原函数的参数个数时只会返回一个新的函数,直接参数够时才返回值。
用途
- 功能内聚
- 降低耦合
- 降低代码的重复性
- 提高代码的适应性
柯里化的实现例子
```javascript function add(a, b, c, d) { // 使其柯里化 return a + b + c + d; }
var curry2Add = progressCurrying(add); // 有达到的目标,与偏函数相似 console.log(carry2Add(1, 2, 3)(4));
// 实现转为柯里化函数 // 在未收够原函数的参数个数时只会返回一个新的函数 function progressCurrying(fn, args) { var _this = this, len = fn.length, //原函数形参长度 args = args || []; //参数收集数据
return function () {
_args = [].slice.call(arguments);
// 加入本次收集到的参数
args = args.concat(_args);
// 如果参数个数小于最初的fn.length,则递归调用,继续收集参数
if (args.length < len) {
return progressCurrying.call(_this, fn, args);
}
// 参数收集完毕,则执行fn
return fn.apply(_this, args);
};
}
<a name="wPie0"></a>
# 反柯里化
让当前的函数不局限于其调用者本身,让函数更加的通用性和泛化(扩大适用范围)。这就是反柯里化解决的问题。
如 Array.prototype.push ,这个方法作用对象数组。<br />可以通过 .call / .apply 的方式更改作用对象,使其对一个类数组对象。
```javascript
Function.prototype.uncurrying = function(){
var fn = this;
return function(){
var _this = Array.prototype.shift.call(arguments);
return fn.apply(_this, arguments);
}
}
// 另一种写法是使用 bind
Function.prototype.uncurrying = function(){
return Function.prototype.call.bind(this);
}
var push = Array.prototype.push.uncurrying();
var obj = {};
console.log(push(obj, 'first', 'second')); // 2
console.log(obj) // {0:"first", 1:"second", length:2}
总结
函数柯里化就是对高阶函数的降阶处理,缩小适用范围,创建一个针对性更强的函数
function(arg1, arg2) // => function(arg1)(arg2)
function(arg1, arg2, ... argN) // => function(arg1)(arg2)...(argN)
反柯里化就是反过来,增加适用范围,让方法使用场景更大
obj.func(arg1, arg2) // => func(obj, arg1, arg2)
也能这样理解
柯里化是在运算前提前传参,可以传递多个参数;
反柯里化是延迟传参,在运算时把原来已经固定的参数或者this上下文等当作参数延迟到未来传递。