機能カリー化と合成機能構成

カレーの実装 

JS関数合成は、複数の単一パラメーター関数を1つのマルチパラメーター関数に結合する操作です。たとえば、a(x)とb(x)を組み合わせてa(b(x))にする場合、それらをまとめてf(a、b、x)と呼びます。ここでのa(x)とb(x)の両方が受け取ることができるパラメーターは1つだけであることに注意してください。a(x、y)やb(a、b、c)などの複数のパラメーターを受け取る場合、関数の合成はより面倒です。

 

このとき、機能カリー化を使用します。いわゆるカリー化は、マルチパラメータ関数をシングルパラメータ関数に変換することです。カリー化操作により、すべての関数が1つのパラメーターのみを受け取るようにすることができます。

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);
  };
}

おすすめ

転載: blog.csdn.net/lianjiuxiao/article/details/112623171