如何在javascript中实现函数调用的任意链表

How to achieve arbitrary chain on function call in javascript?

本文关键字:函数调用 任意 链表 实现 javascript      更新时间:2023-09-26

我已经编写了实现的代码

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

通常你会这样做:

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

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

您不能这样做-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;
}());

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

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

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

以下是实现:

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

有几种不同的方法可以将"任意"数量的参数传递给函数。也许对您的案例最有用的是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

需要注意的两件事:

  • 因为您正在访问arguments对象,所以在函数定义中确实不需要任何类型的arguments列表(即,在sum(a)中不需要a),但通常认为提供函数期望值的一些指示是个好主意
  • arguments对象是类似的array-,但不是真正的数组;除非你想把事情搞得一团糟,否则不要尝试在上面使用数组函数,比如push或pop

然而,至于具体的sum(1)(2)语法——如果这是您所需要的——我很困惑。理论上,要有这样的任意链,你需要你的函数返回一个既是函数又是数字的对象。。。这打破了JavaScript的基本规则。我认为,如果没有对内置对象进行一些非常聪明(而且可能非常危险)的编辑,这是不可能的,除非有非常好的理由,否则通常是不受欢迎的。