由 Haskell Brooks Curry 提出

定义

在计算机科学中,柯里化把接受多个参数的函数编程变为接受一个单一的参数(最初函数的第一个参数)的函数,并且返回接收余下的参数且返回结果的新函数的技术(缩小适用范围,创建一个针对性更强的函数)。

  1. test(1, 2, 3);
  2. test(1)(2)(3);
  3. test(1, 2)(3);
  4. test(1)(2, 3);

柯里化后,在未收够原函数的参数个数时只会返回一个新的函数,直接参数够时才返回值。

用途

  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 || []; //参数收集数据

  1. return function () {
  2. _args = [].slice.call(arguments);
  3. // 加入本次收集到的参数
  4. args = args.concat(_args);
  5. // 如果参数个数小于最初的fn.length,则递归调用,继续收集参数
  6. if (args.length < len) {
  7. return progressCurrying.call(_this, fn, args);
  8. }
  9. // 参数收集完毕,则执行fn
  10. return fn.apply(_this, args);
  11. };

}

  1. <a name="wPie0"></a>
  2. # 反柯里化
  3. 让当前的函数不局限于其调用者本身,让函数更加的通用性和泛化(扩大适用范围)。这就是反柯里化解决的问题。
  4. 如 Array.prototype.push ,这个方法作用对象数组。<br />可以通过 .call / .apply 的方式更改作用对象,使其对一个类数组对象。
  5. ```javascript
  6. Function.prototype.uncurrying = function(){
  7. var fn = this;
  8. return function(){
  9. var _this = Array.prototype.shift.call(arguments);
  10. return fn.apply(_this, arguments);
  11. }
  12. }
  13. // 另一种写法是使用 bind
  14. Function.prototype.uncurrying = function(){
  15. return Function.prototype.call.bind(this);
  16. }
  17. var push = Array.prototype.push.uncurrying();
  18. var obj = {};
  19. console.log(push(obj, 'first', 'second')); // 2
  20. console.log(obj) // {0:"first", 1:"second", length:2}

总结

函数柯里化就是对高阶函数的降阶处理,缩小适用范围,创建一个针对性更强的函数

  1. function(arg1, arg2) // => function(arg1)(arg2)
  2. function(arg1, arg2, ... argN) // => function(arg1)(arg2)...(argN)

反柯里化就是反过来,增加适用范围,让方法使用场景更大

  1. obj.func(arg1, arg2) // => func(obj, arg1, arg2)

也能这样理解

柯里化是在运算前提前传参,可以传递多个参数;
反柯里化是延迟传参,在运算时把原来已经固定的参数或者this上下文等当作参数延迟到未来传递。