【问题标题】:How to achieve arbitrary chain on function call in javascript? [duplicate]如何在javascript中实现函数调用的任意链? [复制]
【发布时间】:2014-10-30 15:12:31
【问题描述】:

我已经写了代码来实现

sum(1)(2) //3

代码如下:

function sum(a) {

  return function(b) { 
    return a+b
 }

}

但我没有解决第二个问题,即如何实现任意数量的链函数调用,如:

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

【问题讨论】:

    标签: javascript chaining


    【解决方案1】:

    通常你会这样做:

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

    然后你可以写:

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

    但有可能破解您所追求的功能:

    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
    

    请不要在生产代码中这样做!

    【讨论】:

    • 这很聪明。正如您的回答所暗示的那样,对于实际使用来说可能太聪明了。然而,它是准确的,非常发人深省。
    • 非常好!如果您愿意,还可以添加 f.toString = function(){ return x+""; }; 以允许使用 alert(sum(1)(2)(3)(4)) 之类的内容。
    【解决方案2】:

    您不能这样做 - sum 函数如何知道您希望它返回答案还是其他函数?

    您可以按照以下方式做一些事情:

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

    这样实现:

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

    【讨论】:

    • 谢谢,但这是书上的一个问题,所以我认为它能够以某种方式做到这一点。
    • 如果你找到答案,我很想看看答案,似乎它需要返回一个也是一个函数的数字
    • @codebox 查看 mintsauce 的答案,它覆盖了返回函数的 valueOf 方法。
    【解决方案3】:

    正如用户代码框所说:这是不可能的。

    您可以做的是将函数的当前参数考虑在内。如果没有参数可以返回结果:

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

    这里是实现:

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

    【讨论】:

    • 不错,比我的更接近他的要求
    【解决方案4】:

    有几种不同的方法可以将“任意”数量的参数传递给函数。也许对您的情况最有用的是arguments 对象。在每个函数的作用域中都有一个类似数组的对象,其中包含传递给函数的所有参数。

    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
    

    尽管该函数似乎只接受一个参数,但您可以插入任意数量的参数,并且该函数将循环遍历所有参数。因此,将其转换为您的代码:

    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
    

    需要注意的两点:

    • 因为您正在访问参数对象,所以您实际上并不“需要”函数定义中的任何类型的参数列表(即您不需要 sum(a) 中的 a),但通常认为提供一些关于函数期望的指示的好主意。
    • 参数对象是数组-类似,但不是真正的数组;不要尝试在其上使用数组函数,例如 push 或 pop,除非你想把事情弄得一团糟。

    至于具体的sum(1)(2) 语法——如果这正是你需要的——我很难过。从理论上讲,要拥有这样的任意链,您需要您的函数返回一个对象,该对象 是一个函数和一个数字......这违反了 JavaScript 的基本规则。我认为如果不对内置对象进行一些非常聪明(并且可能非常危险)的编辑,这是不可能的,除非有非常好的理由,否则通常不赞成这样做。

    【讨论】:

      猜你喜欢
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多