How to chain functions without using prototype?

前端 未结 4 907
既然无缘
既然无缘 2020-12-08 21:42

I have a bunch of useful functions that I have collected during my whole life.

function one(num){
    return num+1;
}

function two(num){
    return num+2;
}         


        
相关标签:
4条回答
  • 2020-12-08 22:22

    The dot syntax is reserved for objects. So you can do something like

    function MyNumber(n) {
        var internal = Number(n);
        this.one = function() {
            internal += 1;
            // here comes the magic that allows chaining:
            return this;
        }
        // this.two analogous
        this.valueOf = function() {
            return internal;
        }
    }
    
    new MyNumber(5).one().two().two().valueOf(); // 10
    

    Or you're going to implement these methods on the prototype of the native Number object/function. That would allow (5).one()...

    0 讨论(0)
  • 2020-12-08 22:39

    A nice and general alternative is creating a custom function composition function

    var go = function(x, fs){
       for(var i=0; i < fs.length; i++){
           x = fs[i](x);
       }
       return x;
    }
    

    You can call it like this:

    go(5, [one, two, two])
    

    I am personaly not a big fan of method chaining since it restricts you to a predefined set of functions and there is kind of an impedance mismatch between values inside the "chaining object" and free values outside.

    0 讨论(0)
  • 2020-12-08 22:47

    Another alternative is to use lodash flow function. For example:

    var five = _.flow(one, two, two)
    five(5)
    

    I prefer assigning a new chain to a variable. It gives it a clear name and encourages re-use.

    Btw, lodash also helps in passing additional arguments to the functions of the chain. For example:

    var addFive = _.flow(
       _.partialRight(_.add, 1),
       _.partialRight(_.add, 2),
       _.partialRight(_.add, 2)
    )
    

    There are many other useful functions to help in functional chaining, e.g., partial, spread, flip, negate, etc.

    0 讨论(0)
  • 2020-12-08 22:48

    In order to avoid having to call toValue at the end of the chain as in @Bergi's solution, you can use a function with attached methods. JS will call toValue automatically when trying to convert to it a primitive type.

    function MyNumber(n) {
        function x () { }
        x.one = function() { n++; return this; };
        x.valueOf = function() { return n; };
        return x;
    }
    

    Then,

    MyNumber(5).one().one()
    > 7
    
    0 讨论(0)
提交回复
热议问题