You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

面试题:实现基于闭包保留状态的JavaScript柯里化加法函数

基于闭包保留状态的JavaScript柯里化加法函数实现

需求说明

需要实现一个支持柯里化的加法函数add,通过闭包持续保留累计求和状态,满足以下调用场景:

  • add(1, 2, 3)(4)(5, 6);
  • add(7, 8);
  • add(9)(10);
  • add();

最终调用add()时需输出55,累计逻辑如下:

  1. add(1, 2, 3)(4)(5, 6) → 累计总和为21
  2. add(7, 8) → 21 + 15 = 36
  3. add(9)(10) → 36 + 19 = 55
  4. add() → 输出最终累计值55

原代码问题分析

你提供的代码无法保留累计状态,核心原因是finalOutput定义在add函数内部,每次调用add都会重新初始化该变量为0,且递归调用add(finalOutput)会创建新的函数上下文,导致之前的累计值完全丢失。

function add(...arg) {
    let finalOutput = 0; // 每次调用add都会重置为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); // 递归调用add,重新创建上下文,丢失之前的finalOutput
        } else {
          return finalOutput;
        }
    };
}

解决方案代码

通过立即执行函数表达式(IIFE)创建闭包,将累计总和变量封装在独立作用域中,确保所有add调用共享同一个状态:

const add = (function() {
  // 闭包内的变量,仅初始化一次,持续保留累计状态
  let total = 0;

  return function(...args) {
    // 无参数调用时,返回当前累计值并重置状态(按需选择是否重置)
    if (args.length === 0) {
      const result = total;
      total = 0; // 如果需要每次调用add()后重置累计,保留此行;否则移除
      return result;
    }

    // 累加本次传入的所有参数到total
    total += args.reduce((acc, num) => acc + num, 0);

    // 返回自身,支持柯里化链式调用
    return add;
  };
})();

代码验证

执行以下调用即可得到预期结果:

add(1, 2, 3)(4)(5, 6); // 累计21
add(7, 8); // 累计36
add(9)(10); // 累计55
add(); // 输出55

逻辑解释

  1. 闭包状态保留:IIFE内部的total变量不会被外部访问,且会被返回的add函数持续引用,因此不会被垃圾回收,实现状态持久化。
  2. 柯里化支持:每次传入参数后,函数返回自身,因此可以链式调用add(a)(b,c)这类形式。
  3. 终止调用:当无参数调用add()时,返回当前累计值,同时可选择重置total以支持下一轮累计。

内容的提问来源于stack exchange,提问作者amit chowdhary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:03:43