函数柯里化curry 与合成函数 compose

41 篇文章 1 订阅

柯里化curry 实现 

JS 函数合成是把多个单一参数函数合成一个多参数函数的运算。例如,a(x) 和 b(x) 组合为 a(b(x)),则合称为 f(a,b,x)。注意,这里的 a(x) 和 b(x) 都只能接收一个参数。如果接收多个参数,如 a(x,y) 和 b(a,b,c),那么函数合成就比较麻烦。

 

这时就要用到函数柯里化。所谓柯里化,就是把一个多参数的函数转化为单一参数函数。有了柯里化运算之后,我们就能做到所有函数只接收一个参数。

var add = function (x) {  //柯里化
    return function (y) {
        return x + y;
    }
}
console.log(add(2) (6));  //8,连续调用
//柯里化函数
function curry (fn) {
    var _argLen = fn.length;  //记录原始函数的形参个数
    var _args = [].slice.call(arguments, 1);  //把传入的第2个及以后参数转换为数组
    function wrap () {  //curry函数
        //把当前参数转换为数组,与前面参数进行合并
        _args = _args.concat([].slice.call(arguments));
        function act () {  //参数处理函数
            //把当前参数转换为数组,与前面参数进行合并
            _args = _args.concat([].slice.call(arguments));
            //如果传入参数总和大于等于原始参数的个数,触发执行条件
            if ((_argLen == 0 && arguments.length == 0) ||
                (_argLen > 0 && _args.length >= _argLen)) {
                //执行原始函数,并把每次传入参数传入进去,返回执行结果,停止curry
                return fn.apply(null, _args);
            }
            return arguments.callee;
        }
        //如果传入参数大于等于原始函数的参数个数,即触发了执行条件
        if ((_argLen == 0 && arguments.length == 0) ||
            (_argLen > 0 && _args.length >= _argLen)) {
            //执行原始函数,并把每次传入参数传入进去,返回执行结果,停止curry
            return fn.apply(null, _args);
        }
        act.toString = function () {  //定义处理函数的字符串表示为原始函数的字符串表示
            return fn.toString();
        }
        return act;  //返回处理函数
    }
    return wrap;  //返回curry函数
}

合成函数实现

在 JS 函数式编程中,经常见到如下表达式运算。

a(b(c(x)));

这是“包菜式”多层函数调用,但不是很优雅。为了解决函数多层调用的嵌套问题,我们需要用到函数合成。其语法格式如下:

var f = compose(a, b, c);  //合成函数
f(x);
递归实现:
const compose = function (...funcs) {
  let len = funcs.length,
    count = len - 1,
    result = null;
  // 首先compse 返回的是一个函数
  return function fn(...args) {
    // 函数体里就是不断执行args函数,将上一个函数的执行结果作为下一个执行函数的输入参数,需要一个count来记录args函数列表的执行情况
    result = args[count].apply(this, args);
    console.log(result);
    // 递归退出条件
    if (count <= 0) {
      count = len - 1;
    } else {
      count--;
      return fn.call(null, result);
    }
  };
};

迭代实现:

function compose(...fns) {
  let isFirst = true;
  return (...args) => {
    return fns.reduceRight((result, fn) => {
      if (!isFirst) return fn(result);
      isFirst = false;
      return fn(...result);
    }, args);
  };
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值