0

我试图通过关闭来制作下一个:

function func(number) {
    var result = number;

    var res = function(num) {
        return result + num;
    };
    return res;
}

var result = func(2)(3)(4)(5)(3);
console.log(result); // 17

我需要收到 2 + 3 + 4 + 5 + 3 = 17 但我收到一个错误:未捕获的 TypeError: number is not a function

4

7 回答 7

9

您必须以某种方式指示链的结束,您将返回结果编号而不是另一个函数。您可以选择:

  • 让它以固定的次数返回一个函数 - 这是使用语法的唯一方法,但它很无聊。看看@PaulS 的回答。您可以让第一次调用 ( func(n)) 提供多少参数sum柯里化的数字。
  • 在某些情况下返回结果,例如在没有参数(@PaulS 的第二个实现)或使用特殊值(null在 @AmoghTalpallikar 的答案中)调用函数时。
  • 在返回值的函数对象上创建一个方法。valueOf()非常适合,因为它将在函数转换为原始值时调用。看看它的实际效果:

    function func(x) {
        function ret(y) {
            return func(x+y);
        }
        ret.valueOf = function() {
            return x;
        };
        return ret;
    }
    
    func(2) // Function
    func(2).valueOf() // 2
    func(2)(3) // Function
    func(2)(3).valueOf() // 5
    func(2)(3)(4)(5)(3) // Function
    func(2)(3)(4)(5)(3)+0 // 17
    
于 2013-08-05T20:22:54.127 回答
8

你在滥用你的功能。

func(2)返回res函数。
调用该函数(3)返回数字5(通过return result + num)。

5不是函数,所以(4)会出错。

于 2013-08-05T19:40:14.223 回答
3

好吧,(2)(3)部分是正确的。调用 func(2) 将返回 you res,这是一个函数。但是,调用 (3) 将返回 的结果res,它是一个数字。因此,当您尝试调用 (4) 时,问题就来了。

对于您要执行的操作,我看不到 Javascript 会如何预测您处于链的末尾,并决定返回一个数字而不是一个函数。也许您可以使用对象属性以某种方式返回具有“结果”属性的函数,但大多数情况下我只是好奇您为什么要尝试以这种方式做事。显然,对于您的具体示例,最简单的方法是将数字相加,但我猜您会在某些方面走得更远。

于 2013-08-05T19:42:52.873 回答
0

如果你想继续调用它,你需要继续返回一个函数,直到你想要你的答案。例如 5 次调用

function func(number) {
    var result = number,
        iteration = 0,
        fn = function (num) {
            result += num;
            if (++iteration < 4) return fn;
            return result;
        };
    return fn;
}
func(2)(3)(4)(5)(3); // 17

你也可以做一些更长的事情,就像这样

function func(number) {
    var result = number,
        fn = function () {
            var i;
            for (i = 0; i < arguments.length; ++i)
                result += arguments[i];
            if (i !== 0) return fn;
            return result;
        };
    return fn;
}
func(2)(3, 4, 5)(3)(); // 17
于 2013-08-05T19:46:02.030 回答
0

我将此标记为重复,但由于该问题也缺少此替代方法,因此我将在此处添加它。如果我正确理解为什么您会认为这很有趣(具有按顺序应用于值列表的任意函数,累积结果),您还应该查看reduce

function sum(a, b) {
    return a + b;
}

a = [2, 3, 4, 5, 3];

b = a.reduce(sum);
于 2013-08-05T20:25:01.660 回答
0

另一种解决方案可能是只调用不带参数的函数以获得结果,但如果使用参数调用它,它会添加到总和中。

function add() {
  var sum = 0;
  var closure = function() {
    sum = Array.prototype.slice.call(arguments).reduce(function(total, num) {
      return total + num;
    }, sum);
    return arguments.length ? closure : sum;
  };
  return closure.apply(null, arguments);
}

console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)); //  function(){}
console.log(add(1, 2, 7)(5)(4)(2, 3)(3.14, 2.86)()); // 30;

于 2016-07-13T12:08:11.400 回答
0

我们可以使用几个辅助函数identitysumk.

sumk使用 continuation 来保留待处理的add计算堆栈,并在调用0第一个计算时展开堆栈()

const identity = x => x

const sumk = (x,k) =>
  x === undefined ? k(0) : y => sumk(y, next => k(x + next))

const sum = x => sumk(x, identity)

console.log(sum())                // 0
console.log(sum(1)())             // 1
console.log(sum(1)(2)())          // 3
console.log(sum(1)(2)(3)())       // 6
console.log(sum(1)(2)(3)(4)())    // 10
console.log(sum(1)(2)(3)(4)(5)()) // 15

于 2017-01-30T17:52:55.480 回答