繁体   English   中英

JavaScript 关闭 - 怎么了?

[英]Closure in JavaScript - whats wrong?

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

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

您必须以某种方式指示链的末端,您将在此处返回结果编号而不是另一个函数。 你有选择:

  • 让它返回一个固定次数的函数——这是像你一样使用语法的唯一方法,但它很无聊。 看看@PaulS 的回答。 您可以使第一次调用 ( func(n) ) 提供curried参数sum的数量。
  • 在某些情况下返回结果,例如在不带参数(@PaulS 的第二个实现)或带有特殊值(@AmoghTalpallikar 的答案中为null )的情况下调用函数时。
  • 在函数对象上创建一个返回值的方法。 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

你在滥用你的功能。

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

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

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

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

如果你想继续调用它,你需要不断返回一个函数,直到你想要你的答案。 例如 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

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

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

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

b = a.reduce(sum);

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

 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;

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

sumk使用延续来保留一个待处理的添加计算的堆栈,并在调用 first ()时用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM