How to achieve arbitrary chain on function call in javascript? [duplicate]

人走茶凉 提交于 2019-12-04 01:24:16

问题


I have written code to achieve

sum(1)(2) //3

the code looks like:

function sum(a) {

  return function(b) { 
    return a+b
 }

}

But I didn't work out the second question, which is how to achieve any arbitrary number of chain function call like:

sum(1)(2) == 3
sum(5)(-1)(2) == 6
sum(6)(-1)(-2)(-3) == 0
sum(0)(1)(2)(3)(4)(5) == 15

回答1:


Normally you'd do something like this:

var add = function(a,b){
    return a+b;
};

var sum = function(){
    return [].reduce.call(arguments, add);
}

And then you can write:

sum(1,2,3,4); // 10

But it is possible to hack the functionality you're after:

var sum = function(x){
    var f = function(y){
        return sum(x+y);
    };
    f.valueOf = function(){
        return x;
    };
    return f;
};

sum(1)(2)(3)(4); // 10

Just don't do it in production code please!




回答2:


You can't do this - how does the sum function know whether you want it to return the answer or another function?

You could do something along these lines though:

sum(0)(1)(2)(3).result()

Implemented like this:

var sum = (function(){
    var total = 0;
    var f = function(n){
        total += n;
        return f;
    };
    f.result = function(){
        return total;
    };
    return f;
}());



回答3:


As user codebox already said: This is not possible.

What you can do instead is to take the current parameter of the function into account. If there is no parameter you can return the result:

sum(1)(2)() == 3

Here is the implementation:

var sum = (function() {
    var total = 0;
    return function add(a) {
        if(a === undefined) {
            return total;
        }
        total += a;
        return add;
    };
}());



回答4:


There's a handful of different ways to pass an "arbitrary" amount of arguments to a function. Perhaps the most useful for your case is the arguments object. In the scope of every function is an array-like object that holds all of the arguments passed to the function.

function shout(msg) {
    for (var i = 0; i < arguments.length; i++)
        console.log(arguments[i]);
}

shout("This", "is", "JavaScript!"); // Logs all three strings, one line at a time

Despite it seeming like the function only accepts one argument, you can plug in as many as you'd like, and the function will cycle through all of them. Thus, converting this for your code:

function sum(a) {
    var total = 0;

    for (var i = 0; i < arguments.length; i++)
        total = total + arguments[i];

    return total;
}

sum(1, 2); // Returns 3

Two things to note:

  • Because you're accessing the arguments object, you really don't "need" any sort of arguments list in the function definition (i.e. you don't need the a in sum(a)), but it's generally considered a good idea to provide some indication of what the function expects.
  • The arguments object is array-like, but is NOT a true array; don't go trying to use array functions on it such as push or pop unless you want to make a mess of things.

As for the specific sum(1)(2) syntax however--if that is very specifically what you need--I'm stumped. In theory, to have an arbitrary chain like that, you'd need your function to return an object that is both a function and a number... which breaks fundamental rules of JavaScript. I don't think it's possible without some extremely clever (and likely extremely dangerous) editing of built in objects, which is generally frowned upon unless there is an extremely good reason for doing so.



来源:https://stackoverflow.com/questions/26656718/how-to-achieve-arbitrary-chain-on-function-call-in-javascript

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