函数组合的意思是, 一个函数, 参数列表为多个函数, 这个函数返回的是一个整合了多个函数功能的函数。
emmm, 好像有点绕。

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

function toUpperCase(str) {
    return str.toUpperCase()
}

function add(str) {
    return str + '!'
}

let f = compose(add, toUpperCase)
console.log(f('Hello world')); // HELLO WORLD! 

就是这样了。函数 f 是将另外两个函数的功能整合到了一起的一个新函数

function compose() {
    var ags = Array.prototype.slice.call(arguments) // 类数组转数组
    var len = ags.length - 1
    return function (x) {
        var res = ags[len](x)
        while (len--){
            res = ags[len](res)
        }
        return res
    }
}

当不知道要多少个函数组合的时候,使用递归的方式无疑要优雅很多。
似乎这个递归跟数组的 reduce 方法好相似。。。
又开始造作:

function compose() {
    var args = Array.prototype.slice.call(arguments) // 类数组转数组
    return function (x) {
        return args.reduceRight(function (res, cb) {
            return cb(res)
        }, x)
    }
}
// HELLO WORLD!

递归需要倒着进行, 所以使用 reduceRight
顺便补一点 reduce 的使用方法

arr.reduce(function (prev, next, index, arr) {}, initialValue)

如果 reduceRight 就是倒着的,index也是倒序的
在这次应用中, next就是数组里面的各个函数, prev也就成了上一次函数执行的结果。初始值就是之前传递进去的字符串(initialValue)
还可以再造作一下:

const compose = (...args) => x => args.reduceRight((res, cb) => cb(res), x)
let f = compose(add, toUppercase)
f('Hello, world') // HELLO WORLD!