关于javascript函数式编程中compose的完成

上一篇文章引见了javascript函数式编程中curry(柯里化)的完成,固然谁人柯里化是有限参数的柯里化,等有机会在补上无穷参数的那一种柯里化,此次主要说的是javascript函数式编程中别的一个很主要的函数composecompose函数的作用就是组合函数的,将函数串连起来实行,将多个函数组合起来,一个函数的输出效果是另一个函数的输入参数,一旦第一个函数最先实行,就会像多米诺骨牌一样推导实行了。

简介

比方有如许的需求,要输入一个名字,这个名字有由firstName,lastName组合而成,然后把这个名字悉数变成大写输出来,比方输入jacksmith我们就要打印出来,‘HELLO,JACK SMITH’
我们斟酌用函数组合的要领来处置惩罚这个题目,须要两个函数greeting, toUpper

var greeting = (firstName, lastName) => 'hello, ' + firstName + ' ' + lastName
var toUpper = str => str.toUpperCase()
var fn = compose(toUpper, greeting)
console.log(fn('jack', 'smith'))
// ‘HELLO,JACK SMITH’

这就是compose大抵的运用,总结下来要注意的有以下几点

  • compose的参数是函数,返回的也是一个函数

  • 因为除了第一个函数的吸收参数,其他函数的吸收参数都是上一个函数的返回值,所以初始函数的参数是多元的,而其他函数的吸收值是一元

  • compsoe函数能够吸收恣意的参数,一切的参数都是函数,且实行方向是自右向左的,初始函数肯定放到参数的最右面

晓得这三点后,就很轻易的剖析出上个例子的实行历程了,实行fn('jack', 'smith')的时刻,初始函数为greeting,实行效果作为参数传递给toUpper,再实行toUpper,得出末了的效果,compose的优点我简朴提一下,假如还想再加一个处置惩罚函数,不须要修正fn,只须要在实行一个compose,比方我们再想加一个trim,只须要如许做

var trim = str => str.trim()
var newFn = compose(trim, fn)
console.log(newFn('jack', 'smith'))

就能够了,能够看出不管保护和扩大都非常的轻易。

完成

例子剖析完了,本着究其基础的准绳,照样要探讨与一下compose究竟是怎样完成的,起首诠释引见一下我是怎样完成的,然后再寻找一下,javascript函数式编程的两大类库,lodash.jsramda.js是怎样完成的,个中ramda.js完成的历程非常函数式。

我的完成

我的思绪是,既然函数像多米诺骨牌式的实行,我起首就想到了递归,下面就一步一步的完成这个compose,起首,compose返回一个函数,为了纪录递归的实行情况,还要纪录参数的长度len,还要给返回的函数增加一个名字f1

var compose = function(...args) {
    var len = args.length
    return function f1() {
        
    }
}

函数体内里要做的事变就是不停的实行args中的函数,将上一个函数的实行效果作为下一个实行函数的输入参数,须要一个游标count来纪录args函数列表的实行情况。

var compose = function(...args) {
    var len = args.length
    var count = len - 1
    var result
    return function f1(...args1) {
        result = args[count].apply(this, args1)
        count--
        return f1.call(null, result)
    }
}

这个就是思绪,固然如许是不可的,没有退出前提,递归的退出前提就是末了一个函数实行完的时刻,也就是count0的时刻,这时刻,有一点要注意,递归退出的时刻,count游标肯定要回归初始状况,末了补充一下代码

var compose = function(...args) {
        var len = args.length
        var count = len - 1
        var result
        return function f1(...args1) {
            result = args[count].apply(this, args1)
            if (count <= 0) {
                count = len - 1
                return result
            } else {
                count--
                return f1.call(null, result)
            }
        }
    }

如许就完成了这个compose函数。厥后我发明递归这个完全能够运用迭代来完成,运用while函数看起来更轻易邃晓,实在lodash.js就是这么完成的。

lodash完成

lodash的思绪同上,不过是用迭代完成的,我就把它的源代码贴过来看一下

var flow = function(funcs) {
    var length = funcs.length
    var index = length
    while (index--) {
        if (typeof funcs[index] !== 'function') {
            throw new TypeError('Expected a function');
        }
    }
    return function(...args) {
        var index = 0
        var result = length ? funcs[index].apply(this, args) : args[0]
        while (++index < length) {
            result = funcs[index].call(this, result)
        }
        return result
    }
}
var flowRight = function(funcs) {
    return flow(funcs.reverse())
}

能够看出,lodash的原本完成是从左到右的,但也供应了从右到左flowRight,还多了一层函数的校验,而且吸收的是数组,不是参数序列,而且从这行var result = length ? funcs[index].apply(this, args) : args[0]能够看出许可数组为空,能够看出照样非常严谨的。我写的就缺乏这类严谨的非常处置惩罚。

结论

此次主要引见了函数式编程中的compose函数的道理和完成要领,因为篇幅缘由,我把盘算剖析的ramda.js源码完成放到下一篇来引见,能够说ramda.js完成的compose越发函数式,须要零丁好好剖析。

    原文作者:dongzhe3917875
    原文地址: https://segmentfault.com/a/1190000008394749
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞