如何实现一个无限累加的 sum 函数
更多描述 实现一个 sum 函数如下所示:
sum(1, 2, 3).valueOf(); //6
sum(2, 3)(2).valueOf(); //7
sum(1)(2)(3)(4).valueOf(); //10
sum(2)(4, 1)(2).valueOf(); //9
sum(1)(2)(3)(4)(5)(6).valueOf(); // 21
追问:
如果不使用 valueOf
,可直接进行计算,如下示例,应如何处理。
//=> 15
sum(1, 2, 3) + sum(4, 5);
//=> 100
sum(10) * sum(10);
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 428
Author 回答者: shfshanyue
这还是字节、快手、阿里一众大厂最为偏爱的题目,实际上有一点技巧问题。
这是一个关于懒计算的函数,使用 sum
收集所有累加项,使用 valueOf
进行计算
- sum 返回一个函数,收集所有的累加项,使用递归实现
- 返回函数带有
valueOf
属性,用于统一计算
代码见 【Q421】如何实现无限累加的一个函数,方便测试与调试
function sum(...args) {
const f = (...rest) => sum(...args, ...rest);
f.valueOf = () => args.reduce((x, y) => x + y, 0);
return f;
}
Author 回答者: haiifeng
这是一个关于懒计算的函数,使用
sum
收集所有累加项,使用valueOf
进行计算
- sum 返回一个函数,收集所有的累加项,使用递归实现
- 返回函数带有
valueOf
属性,用于统一计算function sum(...args) { const f = (...rest) => sum(...args, ...rest); f.valueOf = () => args.reduce((x, y) => x + y, 0); return f; }
看了好多遍才理解,大佬果然是大佬。 关键点在于每次调用后返回自己所返回的东西,也就是函数f。 同时收集每次传进来的参数并做对应的操作。
Author 回答者: Mingeax
这算不算函数柯里化?
Author 回答者: Vi-jay
这还是字节、快手、阿里一众大厂最为偏爱的题目,实际上有一点技巧问题。
这是一个关于懒计算的函数,使用
sum
收集所有累加项,使用valueOf
进行计算
- sum 返回一个函数,收集所有的累加项,使用递归实现
- 返回函数带有
valueOf
属性,用于统一计算代码见 【Q421】如何实现无限累加的一个函数,方便测试与调试
function sum(...args) { const f = (...rest) => sum(...args, ...rest); f.valueOf = () => args.reduce((x, y) => x + y, 0); return f; }
这闭包用的让人虎躯一震 太强了
Author 回答者: wangjs-jacky
写一个啰嗦一点的版本供大家参考: 想法很简单:
- 用一个变量收集所有的参数。
- 返回一个带有 valueOf 属性的 function。
function sum(...args: number[]) {
// allArgs 收集所有的 args
let allArgs = args;
// 返回一个 function 可以接受参数
function fn(...args2) {
allArgs = allArgs.concat(args2);
return fn;
}
// function 上有一个属性叫 valueOf
fn.valueOf = function () {
// valueOf 触发时才开始累加
return allArgs.reduce((res, cur) => (res += cur));
};
return fn;
}
Author 回答者: zfy171
function getNum(…args) { return args.reduce((prev, next) => { return prev + next }, 0) }
Author 回答者: kirazZ1
自己尝试写了一版,不过不是懒计算,调用一次算一次,计算的结果利用闭包缓存:
function sum(...args: number[]) {
const value = args.reduce((pre, cur) => pre + cur, 0);
const _sum = function (..._arg: number[]) {
return sum.call(null, value, ..._arg);
};
_sum.valueOf = () => console.log(value);
return _sum;
}
Author 回答者: justorez
追问:
如果不使用
valueOf
,可直接进行计算,如下示例,应如何处理。//=> 15 sum(1, 2, 3) + sum(4, 5); //=> 100 sum(10) * sum(10);
实现这个效果:覆写 toString
或 Symbol.toPrimitive
即可。
function sum(...args) {
const f = (...fArgs) =>
!fArgs.length ? f.toString() : sum(...args, ...fArgs);
f.toString = () => args.reduce((cur, next) => cur + next);
return f;
}
Author 回答者: Hazel-Lin
function sum(...args) {
const foo = (...rest) => sum(...args, ...rest);
foo.toString = () => args.reduce((x, y) => x + y, 0);
return foo;
}
console.log(sum(1)(2, 3) + sum(1)); // 7
console.log(sum(10) * sum(10)); // 100
被这一波操作秀到了reduce真好用