使用闭合保留价值的咖喱功能

Currying function which retains value using closure

提问人:amit chowdhary 提问时间:10/30/2023 更新时间:10/30/2023 访问量:108

问:

在一次采访中,我被要求编写一个使用闭包(Javascript)保留值的咖喱函数。 示例:执行最后一个添加函数后,上述代码行的输出应为 55。add(1, 2, 3)(4)(5, 6);add(7, 8);add(9)(10);add();

所以它应该是这样的——add(1, 2, 3)(4)(5, 6); -> 21 add(7, 8); -> 21(previous value) + 15 -> 36 add(9)(10); -> 36(previous value) + 19 -> 55 add(); -> 55(final output)

有人可以用解决方案取悦我吗?提前致谢。

我尝试了以下方法,但无法保留该值,因为在每次调用时,finalOutput 变量都会重新初始化为 0。我尝试将其包装在另一个函数中以利用闭包功能,但没有奏效。

function add(...arg) {
    let finalOutput = 0;
    if (arg.length === 0) {
        return finalOutput;
    }
    return function (...newArg) {
        if (newArg.length) {
        let argsArr = [...arg, ...newArg];
        finalOutput = argsArr.reduce((acc, currentValue) => {
            return acc + currentValue;
        });
        return add(finalOutput);
        } else {
          return finalOutput;
        }
    };
}
JavaScript 闭包 currying

评论

0赞 Bergi 10/30/2023
任务要求一个全局变量,这是一个坏主意。你的方法要好得多。
0赞 Afzal K. 10/30/2023
我试过了,但由于嵌套调用,调用堆栈大小超过

答:

1赞 Nick Parsons 10/30/2023 #1

您可以创建一个包装函数(例如),用于包装存储总和的代码。该包装函数将返回您的函数,您可以将其存储在变量 () 中,然后用于获取总输出,例如:createAdderaddadd

function createAdder() {
  let finalOutput = 0;
  return function add(...args) {
    if(args.length === 0)
      return finalOutput;
    
    finalOutput += args.reduce((sum, v) => sum + v, 0);
    return add;
  }
}


const add = createAdder();

add(1, 2, 3)(4)(5, 6);
add(7, 8);
add(9)(10);
console.log(add());

评论

0赞 Afzal K. 10/30/2023
为什么不使用 IIFE 创建专用范围
0赞 Nick Parsons 10/30/2023
@AfzalK。那也行得通。我想这样你就有机会在需要时创建多个加法器“实例”,每个实例都独立地保持自己的计数。
0赞 Afzal K. 10/30/2023 #2

我们可以通过检查是否有任何参数传递给函数来做到这一点。如果没有,则返回总值,这样我们就可以在没有任何参数的情况下调用 并获取累积值。add()

function add(...args) {
  if(!add.total) add.total = 0;
  
  if(!args || args.length === 0) {
    let total = add.total;
    add.total = undefined; // reset once retrieved
    return total;
  }
  
  add.total += args.reduce((sum, v) => sum + v, 0);
  return add;
}

add(1, 2, 3)(4)(5, 6);
add(7, 8);
add(9)(10);
console.log(add());

add(9)(10);
console.log(add());

评论

0赞 Bergi 10/30/2023
最好只是在函数外部声明,而不是将其存储为函数对象上的可选属性。let total = 0
0赞 Afzal K. 10/30/2023
@Bergi OP不想要那样吗?
0赞 Afzal K. 10/30/2023
稍微修改了一下,所以一旦访问它,它就会重置总数,然后重新开始
0赞 Bergi 10/31/2023
OP 要求闭包,他们没有要求函数属性
0赞 Afzal K. 10/31/2023
明显地。。。。。。