前端JS:柯里化函数的实现和应用

柯里化其实本身是固定一个可以预期的参数,并返回一个特定的函数,处理批特定的需求。这增加了函数的适用性,但同时也降低了函数的适用范围。

函数柯里化 不仅仅是提高了代码的合理性,更重的它突出一种思想---降低适用范围,提高适用性

函数柯里化的通用实现:

function curring(fn){
    var slice=Array.prototype.slice,
        _args=slice.call(arguments,1);
    return function(){
        var __inargs=slice.call(arguments);
        return fn.apply(null,_args.concat(__inargs));
    }    
}
    // 原始的加法函数
    function origPlus(a, b) {
      return a + b;
    }
    
    // 柯里化后的plus函数
    function plus(a) {
      return function(b) {
        return a + b;
      }
    }
    
    // ES6写法
    const plus = a => b => a + b;
复制代码

柯里化

  • 就是一个部分配置多参数函数的过程
  • 每一步都返回一个接受单个参数的部分配置好的函数。

应用场景:

  • 提高适用性: 【通用函数】解决了兼容性问题,但同时也会再来,使用的不便利性,不同的应用场景往,要传递很多参数,以达到解决特定问题的目的。有时候应用中,同一种规则可能会反复使用,这就可能会造成代码的重复性。

看下面一个例子: function square(i) { return i * i; }

function dubble(i) {
    return i *= 2;
}

function map(handeler, list) {
    return list.map(handeler);
}

// 数组的每一项平方
map(square, [1, 2, 3, 4, 5]);
map(square, [6, 7, 8, 9, 10]);
map(square, [10, 20, 30, 40, 50]);
// ......

// 数组的每一项加倍
map(dubble, [1, 2, 3, 4, 5]);
map(dubble, [6, 7, 8, 9, 10]);
map(dubble, [10, 20, 30, 40, 50]);
复制代码

例子中,创建了一个map通用函数,用于适应不同的应用场景。显然,通用性不用怀疑。同时,例子中重复传入了相同的处理函数:square和dubble。

应用中这种可能会更多。当然,通用性的增强必然带来适用性的减弱。但是,我们依然可以在中间找到一种平衡。

  • 柯里化改造

      function square(i) {
          return i * i;
      }
      
      function dubble(i) {
          return i *= 2;
      }
      
      function map(handeler, list) {
          return list.map(handeler);
      }
      
      var mapSQ = currying(map, square);
      mapSQ([1, 2, 3, 4, 5]);
      mapSQ([6, 7, 8, 9, 10]);
      mapSQ([10, 20, 30, 40, 50]);
      // ......
      
      var mapDB = currying(map, dubble);
      mapDB([1, 2, 3, 4, 5]);
      mapDB([6, 7, 8, 9, 10]);
      mapDB([10, 20, 30, 40, 50]);
      // ......
    复制代码
  • 固定易变因素:

    • 柯里化的特性决定了他的应用场景,提前把易变因素通过传参固定下来,生成一个更加明确的函数。典型应用是bind()函数,用以固定this这个易变对象;

    talk is cheap,show me the code:

      Function.prototype.bind=function(context){
          //   引用this 对象;  
          var _this=this,
              _args=Array.prototype.slice.call(arguments,1); // 获取当前传参数组;
          return function(){
              return _this.apply(context,_args.concat(Array.prototype.slice.call(arguments)));
          }
              
    
      }
    复制代码
  • 延迟执行:

    • 不断的柯里化,累计传入的参数,最后执行;

        var add = function() {
        var _this = this,
        _args = arguments
        return function() {
            if (!arguments.length) {
                var sum = 0;
                for (var i = 0,
                c; c = _args[i++];) sum += c
                return sum
            } else {
                Array.prototype.push.apply(_args, arguments) return arguments.callee
            }
        }
      复制代码

      }

        add(1)(2)(3)(4)();//10
      复制代码

    通用写法:

     var curry = function(fn) {
      var _args = []
      return function cb() {
          if (arguments.length == 0) {
              return fn.apply(this, _args)
          }
          Array.prototype.push.apply(_args, arguments);
          return cb;
      }
    复制代码

    }

参考:柯里化的应用场景 参考:自动柯里化的实现

转载于:https://juejin.im/post/5cbac95e6fb9a068b52fbeeb

你可能感兴趣的:(前端JS:柯里化函数的实现和应用)