谈谈函数组合式compose及build设计模式

23,828次阅读
没有评论

共计 2471 个字符,预计需要花费 7 分钟才能阅读完成。

前言

今天主要介绍函数式编程中有一个比较重要的概念就是函数组合(compose), 组合多个函数,同时返回一个新的函数。调用时,组合函数按顺序从右向左执行。右边函数调用后,返回的结果,作为左边函数的参数传入,严格保证了执行顺序,这也是 compose 主要特点。另外介绍一下 build 设计模式,大家可以自行体会一下其中的异同。

组合两个函数

compose 非常简单,通过下面示例代码,就非常清楚

function compose (f, g) {return function(x) {return f(g(x));
    }
}

var arr = [1, 2, 3],
    reverse = function(x){return x.reverse()},
    getFirst = function(x) {return x[0]},
    compseFunc = compose(getFirst, reverse);

compseFunc(arr);   // 3

组合任意个函数

上面组合了两个函数的 compose, 也让我们了解了组合的特点,接着我们看看如何组合更多的函数,因为在实际应用中,不会像入门介绍的代码那么简单。

主要注意几个关键点:

利用 arguments 的长度得到所有组合函数的个数

reduce 遍历执行所有函数。

    var compose = function() {var args = Array.prototype.slice.call(arguments);

      return function(x) {if (args.length>= 2) {return args.reverse().reduce((p, c) => {return p = c(p)
         }, x)

       } else {return args[1] && args[1](x);
       }
      }
    }

    // 利用上面示例 测试一下。var arr = [1, 2, 3],
    reverse = function(x){return x.reverse()},
    getFirst = function(x) {return x[0]},
    trace = function(x) {console.log('执行结果:', x); return x}


    compseFunc = compose(trace, getFirst, trace, reverse);

compseFunc(arr);   
 // 执行结果:(3) [3, 2, 1]
 // 执行结果:3
 // 3

如此实现,基本没什么问题,变量 arr 在管道中传入后,经过各种操作,最后返回了结果。

function compose(...funcs) {return funcs.reduce((prev, cur) => {return (...args) => prev(cur(...args))
  })
}

const toUpperCase = function(x) {return x.toUpperCase(); };
const exclaim = function(x) {return x + '!';};
var shout = compose(exclaim, toUpperCase);

shout("send in the haorooms");

pipe 管道的认识

认识 pipe

函数式编程(FP)里面跟 compose 类似的方法,就是 pipe。

pipe, 主要作用也是组合多个函数,称之为 ’ 流或者管道,肯定得按照正常方法,从左往右调用函数,与 compose 调用方法相反。

ES6 实现 Compose function

先看下 compose 最基础的两参数版本,

const compose = (f1, f2) => value => f1(f2(value));

利用箭头函数,非常直接的表明两个函数嵌套执行的关系,

接着看多层嵌套。

(f1, f2, f3...) => value => f1(f2(f3));

实现 pipe

前面提到 pipe 是反向的 compose,pipe 正向调用也导致它实现起来更容易。

pipe = (...fns) => x => fns.reduce((v, f) => f(v), x)

一行代码就实现了 pipe, 套用上面抽象出来的表达式,reduce 刚好正向遍历所有函数,参数 x 作为传递给函数的初始值,后面每次 f(v)执行的结果,作为下一次 f(v)调用的参数 v, 完成了函数组合调用。

或者,可以把函数组合中,第一个函数获取参数后,得到的结果,最为 reduce 遍历的初始值。

pipe = (fn,...fns) => (x) => fns.reduce((v, f) => f(v), fn(x));

利用 es6 提供的 rest 参数,用于获取函数的多余参数. 提取出第一个函数 fn,多余函数参数放到 fns 中,fns 可以看成是数组,也不用像 arguments 那种事先通过 Array.prototype.slice.call 转为数组,arguments 对性能损耗也可以避免。fn(x) 第一个函数执行结果作为 reduce 初始值。

build 模式

下面介绍一下 build 模式,

build 模式案例代码如下:

let Ctx = function (a1, a2, a3) {
    this.a1 = a1;
    this.a2 = a2;
    this.a3 = a3;
}

let CtxBuilder = function () {
    let a1, a2, a3;
    return {setA1: function (a1) {
            this.a1 = a1;
            return this;
        },
        setA2: function (a2) {
            this.a2 = a2;
            return this;
        },
        setA3: function (a3) {
            this.a3 = a3;
            return this;
        },
        build: function () {return new Ctx(this.a1, this.a2, this.a3)
        }
    }
}

let ctxBuilder = new CtxBuilder().setA1('a1')
    .setA2('a2')
    .setA3('a3');
let ctx = ctxBuilder.build();

大家一看就懂。

小结

上面讲了组合多个函数,及 build 模式,打包多个函数的方式,这些方式在工作中经常有用到,因此在这里介绍一下。希望对大家有帮助,本文是 haorooms 博客整理,欢迎关注 前端博客,haorooms 博客。

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于1970-01-01发表,共计2471字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)