问题
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;
}
I can call them with two(two(one(5)))
But I would prefer to use (5).one().two().two()
How can I achieve this without using prototype?
I tried to see how underscore chain works, but their code is too intense to understand it
回答1:
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()...
回答2:
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
回答3:
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.
回答4:
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.
来源:https://stackoverflow.com/questions/9338439/how-to-chain-functions-without-using-prototype