如何实现支持多调用形式的参数累加add函数?
实现支持任意调用形式的add函数
这个问题其实很好解决,核心是利用JavaScript的闭包和隐式类型转换特性,让函数既能支持链式调用,又能在需要输出结果时返回累加的总和。
核心思路
- 用闭包持久化保存累加的总和,每次调用函数时,将传入的所有参数加到总和里;
- 返回一个新的函数,这个函数可以继续接收参数并重复累加过程;
- 重写返回函数的
toString和valueOf方法,让函数在被转换为原始值(比如打印、参与运算)时,返回当前的累加总和。
代码实现
function add(...args) { // 计算当前传入参数的总和 const total = args.reduce((acc, num) => acc + num, 0); // 定义累加器函数,用于链式调用 const accumulator = (...nextArgs) => { // 递归调用add,把之前的总和和新参数一起传入 return add(total, ...nextArgs); }; // 重写toString,确保打印或转换为字符串时返回总和 accumulator.toString = () => total; // 重写valueOf,确保参与数值运算时返回总和 accumulator.valueOf = () => total; return accumulator; }
测试验证
我们来测试你提到的几种调用场景:
console.log(add(1, 2)); // 输出 3 console.log(add(1)(2, 3)(4)); // 输出 10 console.log(add(1)(2, 3)(4)(5, 6)(7, 8, 9)); // 输出 45 // 甚至可以直接参与数值运算 console.log(add(1)(2) + 3); // 输出 6 console.log(+add(1, 2)(3)); // 输出 6
原理说明
- 闭包的作用:每次调用
add时,都会创建一个新的total变量保存当前累加的总和,而返回的accumulator函数会闭包这个变量,确保后续链式调用时能继续累加; - 隐式类型转换:当我们尝试打印函数或者让函数参与数值运算时,JavaScript会自动调用函数的
toString或valueOf方法。我们重写这两个方法,让它们返回当前的总和,从而实现“调用结束后得到结果”的效果; - 可变参数处理:使用ES6的剩余参数
...args,可以接收任意数量的参数,完美适配你需要的多种传参形式。
如果你想用ES6箭头函数实现,写法更简洁,核心逻辑完全一致:
const add = (...args) => { const total = args.reduce((a, b) => a + b, 0); const accumulator = (...nextArgs) => add(total, ...nextArgs); accumulator.toString = () => total; accumulator.valueOf = () => total; return accumulator; };
内容的提问来源于stack exchange,提问作者Vaibhav Pachauri
相关产品推荐
相关产品推荐

