JavaScript 中的关闭 - 有什么问题?

IT技术 javascript closures
2021-02-06 00:17:44

我试图用闭包做下一个:

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 但是我得到一个错误:Uncaught TypeError: number is not a function

6个回答

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

  • 让它返回一个固定次数的函数——这是像你一样使用语法的唯一方法,但它很无聊。看看@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
    
不过在我的版本中。如果我打电话。f(4)(5) 结果变为 9。nxt 次 f(1)(3)(null) 将给出 13 而不是 4!:(
2021-03-15 00:17:44

你在滥用你的功能。

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

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

只是为了有趣,我试图通过闭包来做到这一点。
2021-03-25 00:17:44
@ user2056866 很难看出这有什么实际用途,所以这很可能是功课。您是否正在尝试创建递归函数?如果是这样,你就有点不对劲了。
2021-03-31 00:17:44
@ user2056866:试试我的回答。它不完全是您想要的方式,但几乎相同。
2021-04-10 00:17:44

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

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

就像我说的,你用这种方式调用它的整个方法很奇怪。返回具有链可调用函数的对象是否更容易接受?即,func().addmore(3).addmore(5).addmore(7).getResult()这通常是 JQuery 所做的。
2021-03-15 00:17:44
是的,这只是为了有趣。但我还是不明白怎么会是对的。
2021-03-28 00:17:44

如果你想继续调用它,你需要不断返回一个函数,直到你想要你的答案。例如 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
我没有否决您的答案,但它仅适用于这么多数量的 ()。它不是动态的。
2021-03-14 00:17:44
@AmoghTalpallikar 好吧,我是为 OP 示例编写的,编辑后的工作方式略有不同
2021-04-10 00:17:44

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

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

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

b = a.reduce(sum);
不要忘记初始化reduce,以防它a是一个空数组。
2021-04-03 00:17:44