How to chain functions without using prototype?

巧了我就是萌 提交于 2019-11-28 07:35:15

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()...

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

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!