Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 84 题:请实现一个 add 函数,满足以下功能。 #134

Open
yygmind opened this issue May 30, 2019 · 92 comments
Open

第 84 题:请实现一个 add 函数,满足以下功能。 #134

yygmind opened this issue May 30, 2019 · 92 comments

Comments

@yygmind
Copy link
Contributor

yygmind commented May 30, 2019

add(1); 	// 1
add(1)(2);  	// 3
add(1)(2)(3)  // 6
add(1)(2, 3);   // 6
add(1, 2)(3);   // 6
add(1, 2, 3);   // 6
@yygmind
Copy link
Contributor Author

yygmind commented May 30, 2019

之前写过 2 篇文章,可以参考一二。
1、【进阶 6-1 期】JavaScript 高阶函数浅析
2、【进阶 6-2 期】深入高阶函数应用之柯里化

其中第一篇文章给出了前三个功能的实现,并没有覆盖到后面三种。
第二篇文章实现了一个通用的柯里化函数,覆盖实现了所有功能。

@yygmind
Copy link
Contributor Author

yygmind commented May 30, 2019

实现 1:

function currying(fn, length) {
  length = length || fn.length; 	// 注释 1
  return function (...args) {			// 注释 2
    return args.length >= length	// 注释 3
    	? fn.apply(this, args)			// 注释 4
      : currying(fn.bind(this, ...args), length - args.length) // 注释 5
  }
}

实现 2:

const currying = fn =>
    judge = (...args) =>
        args.length >= fn.length
            ? fn(...args)
            : (...arg) => judge(...args, ...arg)

其中注释部分

  • 注释 1:第一次调用获取函数 fn 参数的长度,后续调用获取 fn 剩余参数的长度

  • 注释 2:currying 包裹之后返回一个新函数,接收参数为 ...args

  • 注释 3:新函数接收的参数长度是否大于等于 fn 剩余参数需要接收的长度

  • 注释 4:满足要求,执行 fn 函数,传入新函数的参数

  • 注释 5:不满足要求,递归 currying 函数,新的 fn 为 bind 返回的新函数(bind 绑定了 ...args 参数,未执行),新的 length 为 fn 剩余参数的长度

@ZodiacSyndicate
Copy link

const curry = (fn, arity = fn.length, ...args) =>
  arity <= args.length ? fn(...args) : curry.bind(void 0, fn, arity, ...args);

@zhouyangit
Copy link

function add() {
  let args = [].slice.call(arguments);
  let fn = function(){
   let fn_args = [].slice.call(arguments)
   return add.apply(null,args.concat(fn_args))
 }
fn.toString = function(){
  return args.reduce((a,b)=>a+b)
}
return fn
}

@ablikim915
Copy link

function add(){
	let args = [...arguments];
	let addfun = function(){
		args.push(...arguments);
		return addfun;
	}
	addfun.toString = function(){
		return args.reduce((a,b)=>{
			return a + b;
		});
	}
	return addfun;
}

@ablikim915
Copy link

ablikim915 commented May 30, 2019

还有一种方法

function add(){
	if(arguments.length === 0){
		let num = 0;
		add.args.forEach(v=>{
			num += v;
		});
		add.args = null;
		return num;
	}else{
		add.args = add.args ? add.args : [];
		add.args = add.args.concat([...arguments]);
		return add;
	}
}
add(1)(2)(3)();
add(1, 2)(3)(8)();

@GitHdu
Copy link

GitHdu commented May 30, 2019

function curry (fn) {
  const finalLen = fn.length
  let args = [].slice.call(this,1)
  return function currying () {
    args = args.concat(Array.from(arguments))
    const len = args.length
    return len >= fn.length ? fn.apply(this, args) : currying
  }
}
function add (a,b,c) {
  return a+b+c
}
const add1 = curry(add)
console.log(add1(1, 2)(3))

@CoffeeWorm
Copy link

function add(...args) {
  let sum = 0;
  const innerAdd = (...args) => {
    args.forEach(i => (sum += i));
    return innerAdd;
  };
  innerAdd.toString = () => sum;
  return innerAdd(...args);
}

@seognil
Copy link

seognil commented May 30, 2019

如果要做成高阶函数以便支持任意迭代器,累加器的初始值设定要麻烦一点
尤其是考虑到任意长度输入和空输入,要多一些判断逻辑。

写了一个支持以上所有特性的

const curryReducer = (fn) => {
  return (...args) => {
    let runned = false;
    const chain = (...args) => {
      if (!args.length) return chain;
      chain.acc = (runned ? [chain.acc] : []).concat(args).reduce(fn);
      !runned && (runned = true);
      return chain;
    };
    chain.acc = undefined;
    chain.toString = () => chain.acc;
    return chain(...args);
  };
};
// * ---------------- simple add function

const add = curryReducer((a, e) => a + e);

console.log('' + add(1, 2, 3)()(4, 5)(6)(7)(8, 9, 10));
const method = {
  add: (a, e) => a + e,
  minus: (a, e) => a - e,
  times: (a, e) => a * e,
  devide: (a, e) => a / e,
};
Object.values(method).forEach((e) => {
  console.log('batch test -------------- method is: ', e);
  const chainFn = curryReducer(e);
  console.log('' + chainFn());
  console.log('' + chainFn(6));
  console.log('' + chainFn(6, 2));
  console.log('' + chainFn(6)(2));
  console.log('' + chainFn()(6)(2));
  console.log('' + chainFn(6, 2, 3));
  console.log('' + chainFn(6, 2)(3));
  console.log('' + chainFn(6)(2)(3));
});

@linchengzzz
Copy link

linchengzzz commented May 30, 2019

function add(...a) {
    let sum = a.reduce((p, n) => p + n);

    function next(...b) {
        let _sum = b.reduce((p, n) => p + n);
        sum = sum + _sum;
        return next;
    }

    next.toString = function () {
        return sum;
    };

    return next;
}

@wjryours
Copy link

wjryours commented May 31, 2019

function currying(fn, length) {
  length = length || fn.length; 	// 注释 1
  return function (...args) {			// 注释 2
    return args.length >= length	// 注释 3
    	? fn.apply(this, args)			// 注释 4
      : currying(fn.bind(this, ...args), length - args.length) // 注释 5
  }
}
const sum = function(t,y,u){
    let args = [].slice.call(arguments)
    return args.reduce((a, b) => a + b)
} ;
    const add = currying(sum);
    console.log(add(1,2)(2)(9)) ;  	// Uncaught TypeError: add(...)(...) is not a function
请问这个调用这个柯里化函数sum中的形参还要自己手动补吗?
我看这个形参少于实际调用add函数时就会报错,还是我调用的方式错了呢?
@yygmind

@yygmind
Copy link
Contributor Author

yygmind commented May 31, 2019

@wjryours sum 函数定义的参数长度为 3,调用时参数为 4,所以问题出在这里

@ryanZiegler
Copy link

ryanZiegler commented May 31, 2019

@wjryours sum 函数定义的参数长度为 3,调用时参数为 4,所以问题出在这里

柯里化生成的 add 函数若是存储的形参个数达不到定义的参数长度, 则是返回 [Function]

那么如题 add(1) ==>1 , add(1)(2) ==> 3 则不是没有实现吗

@wjryours
Copy link

@wjryours sum 函数定义的参数长度为 3,调用时参数为 4,所以问题出在这里

柯里化生成的 add 函数若是存储的形参个数达不到定义的参数长度, 则是返回 [Function]

那么如题 add(1) ==>1 , add(1)(2) ==> 3 则不是没有实现吗

我想表达的就是这个意思,按照你这个写法那些基本的功能都通过不了,可以解答一下吗@yygmind

@seognil
Copy link

seognil commented May 31, 2019

@wjryours sum 函数定义的参数长度为 3,调用时参数为 4,所以问题出在这里

柯里化生成的 add 函数若是存储的形参个数达不到定义的参数长度, 则是返回 [Function]
那么如题 add(1) ==>1 , add(1)(2) ==> 3 则不是没有实现吗

我想表达的就是这个意思,按照你这个写法那些基本的功能都通过不了,可以解答一下吗@yygmind

我觉得题目出的不好(描述有歧义)。
我的理解里,题目本身和柯里化是有差异的,
题目更像是迭代器而不是柯里化

如果是柯里化,那么缺少参数的时候是等待所有参数到齐则再开始进行运算,并返回计算结果。
(因为不是所有方法都像 add 一样简单,能支持部分参数计算,不然因为缺少参数,计算逻辑报错了怎么办?)
参数不足的时候返回一个中间 function,以便继续调用。

至于直接能读到(toString),这是一个 trick。
对于柯里化这个高阶方法来说,我觉得不应该一起实现。
就像我说的,是应该等参数到齐再计算(固定参数 function 的 length),
可以参考一下 lodash 或者 ramda 里的 curry

至于如何实现题目本身
(任意长度也能返回计算结果,也就是说,调用一次执行一次)
(像我上面说的,更像是实现一个迭代器,add 只是一个算子)
可以参考一下我的答案
#134 (comment)
Inspired by @CoffeeWorm
#134 (comment)

@B2D1
Copy link

B2D1 commented Jun 20, 2019

const curry = fn => {
    const len = fn.length;
    return function curried(...args) {
        if (args.length === len) {
            return fn.apply(null, args);
        }
        return (..._args) => {
            return curried.apply(null, [...args, ..._args]);
        };
    };
};

const sum = (x, y, z) => x + y + z;
const add = curry(sum);

// 6
add(1, 2, 3);

// 6
add(1,2)(3);

// 6
add(1)(2,3);

// 6
add(1)(2)(3);

@woyiweita
Copy link

 // 第一步,先实现加和运算

            var add = function (a, b) {
                return a + b;
            }

            var currying = function (fn, defineVal = 0) {
                return function (...args) { // 第一次调用的是这个函数
                    // 每次执行前先进行和的初始化
                    var sum = defineVal;

                    function func(...argts) { // 第二次之后调用的是这个函数
                        if (args.length === 0) {
                            return func.toString();
                        } else {
                            argts.unshift(sum);
                            sum = argts.reduce(fn);
                            return func;
                        }
                    }
                    func.toString = () => sum;
                    return func(...args);
                }
            }

            var add = currying(add);
            console.info(add(1)); // => 1
            console.info(add(1)(2)); // => 3
            console.info(add(1)(2)(3)); // => 6
            console.info(add(1, 2)(3)); // => 6
            console.info(add(1)(2, 3)); // => 6
            console.info(add(1, 2, 3)); // => 6
            console.info(add(1, 2, 3)(4)); // => 10

@libin1991
Copy link

function add(...x) {
			var sum = x.reduce((a,b)=>a+b,0)
			var tmp = function(...y) {
				sum =sum+y.reduce((a,b)=>a+b,0)
				return tmp;
			};
			tmp.toString = function() {
				return sum;
			};
			return tmp;
		}
		
		console.log(+add(1)(2)(3))   // 6
		console.log(+add(1)(2,3))    // 6
		console.log(+add(1,2)(3))    // 6
		console.log(+add(1)(2)(3,4))   //10
		
		
		add(1)(2)(3).valueOf
		//ƒ valueOf() { [native code] }
		add(1)(2)(3).valueOf()
		//ƒ 6
		+add(1)(2)(3).valueOf()
		//6
		+""+add(1)(2)(3).valueOf()
		//6
	</script>

@linushp
Copy link

linushp commented Jul 11, 2019

`

function add() {

    var sum = function (arr) {
        var curSum = 0;
        for (var i = 0; i < arr.length; i++) {
            var obj = arr[i];
            if(obj){
                curSum = curSum + obj;
            }
        }
        return curSum;
    };

    var result = function () {
        var xx = Array.from(arguments);
        xx.push(result._lastSum);
        return add.apply({},xx);
    };

    result.valueOf = function () {
        return result._lastSum;
    };
    result.toString = function () {
        return result._lastSum ;
    };

    result._lastSum  = sum(arguments);

    return result;
}

`

@negativeentropy9
Copy link

function add() {
  return Array.from(arguments).reduce((pre, item) => pre + item, 0)
}

function curry(fn) {
  let params = [];

  function result() {
    params.push(...arguments)

    return result;
  }

  result.toString = () => { 
    const tempParams = params;
    params = [];

    return fn.call(null, ...tempParams) 
  }

  return result;
}

@harryliuy
Copy link

harryliuy commented Jul 17, 2019

let timer = null
function add(...arg1){
	return function(...arg2){
		let arg = [...arg1,...arg2]
		clearTimeout(timer)
		timer = setTimeout(()=>{
			console.log(arg.reduce((p,c)=>p+c))
		},0)
		return add(...arg);
	}
}

add(2,3)(4)(5,6)(9)()(1) //30

@gitHber
Copy link

gitHber commented Jul 18, 2019

function add(...args) { 
  add.params = add.params.concat(args)
  return add;
}
add.params = []
add.toString = function() {
  var val = add.params.reduce((a,b) => a+b)
  add.params = []
  return val;
}
function add(...args) {
  var f = function(...args1) {
    return add.apply(null, [...args, ...args1])
  }
  f.toString = () => args.reduce((a,b)=>a+b)
  return f
}

@Yxiuchao
Copy link

诸位真的是大佬---膜拜了 我看了半天算是看懂函数柯里化的应用了

function Add(a, b, c) {
  return a + b + c;
}
function cuuring(fn) {
  let finallen = fn.length;
  var args = []
  return function digui() {
    var innerargs = Array.prototype.slice.call(arguments);
    args = args.concat(innerargs);
    return args.length >= finallen ? fn.apply(null, args) : digui;
  }
}
var add1 = cuuring(Add);
console.log(add1(1)(2)(3))

@xiabeizi
Copy link

let timer = null
function add(...arg1){
	return function(...arg2){
		let arg = [...arg1,...arg2]
		clearTimeout(timer)
		timer = setTimeout(()=>{
			console.log(arg.reduce((p,c)=>p+c))
		},0)
		return add(...arg);
	}
}

add(2,3)(4)(5,6)(9)()(1) //30

看来半天 不明白 toString 是怎么调用的...
看你的回答 太真实了

@PatrickLh
Copy link

感觉关键点在重写函数toString方法啊,我就一直在想,怎么又返回函数,而最后又输出结果,真棒!

@xtxt5555
Copy link

xtxt5555 commented Jul 28, 2019

function add(...num) {
    let res = 0 //第一次调用函数时生成一个闭包来存储结果
    num.forEach(item => res += item) //遍历输入参数加到res上

    let ret = function (...num) {
      num.forEach(item => res += item)
      return ret
    }

    ret.toString = function () {
      return res
    }

    ret.valueOf = function () {
      return res
    }

    return ret
  }
  console.log(add(1)); // 1
  console.log(add(1)(2)); // 2
  console.log(add(1)(2)(3)); // 6
  console.log(add(1)(2)(3,7)(4,5,6));// 28 

使用了一个闭包完成了这个效果

@w3cmark
Copy link

w3cmark commented Aug 5, 2019

function add(...num) {
    let res = 0 //第一次调用函数时生成一个闭包来存储结果
    num.forEach(item => res += item) //遍历输入参数加到res上

    let ret = function (...num) {
      num.forEach(item => res += item)
      return ret
    }

    ret.toString = function () {
      return res
    }

    ret.valueOf = function () {
      return res
    }

    return ret
  }
  console.log(add(1)); // 1
  console.log(add(1)(2)); // 2
  console.log(add(1)(2)(3)); // 6
  console.log(add(1)(2)(3,7)(4,5,6));// 28 

使用了一个闭包完成了这个效果

你这里输出的结果其实是 f 1f 6...

image

@caihaihong
Copy link

function add(...firstArgs) {
const result = firstArgs.reduce((pre, now) => pre + now);
const fn = (...args) => {
return add(...args, result);
};
fn.toString = () => result;
return fn;
}

学到了,fn.toString();

@xtxt5555
Copy link

function add(...num) {
    let res = 0 //第一次调用函数时生成一个闭包来存储结果
    num.forEach(item => res += item) //遍历输入参数加到res上

    let ret = function (...num) {
      num.forEach(item => res += item)
      return ret
    }

    ret.toString = function () {
      return res
    }

    ret.valueOf = function () {
      return res
    }

    return ret
  }
  console.log(add(1)); // 1
  console.log(add(1)(2)); // 2
  console.log(add(1)(2)(3)); // 6
  console.log(add(1)(2)(3,7)(4,5,6));// 28 

使用了一个闭包完成了这个效果

你这里输出的结果其实是 f 1f 6...

image

在不知道会一直调用多少次的情况下, 不返回一个函数, 怎么能够继续调用呀

@negativeentropy9
Copy link

function add() {
    const params = [...arguments]

    recur.toString = acc;

    return recur()

    function acc() {
        return params.reduce((acc, item) => {
            acc += item;

            return acc;
        }, 0);
    }

    function recur() {
        params.push(...arguments);

        if (params.length >= 3) {
            return acc()
        } else {
            return recur
        }
    }
}

console.log("debug-", add(1, 2));
console.log("debug-", add(1));
console.log("debug-", add(1, 2)(3));
console.log("debug-", add(1)(2, 3));
console.log("debug-", add(1)(2)(3));
console.log("debug-", add(1, 2, 3));

@pureZjr
Copy link

pureZjr commented Feb 22, 2021

function add() {
  let args = [].slice.call(arguments);
  let fn = function(){
   let fn_args = [].slice.call(arguments)
   return add.apply(null,args.concat(fn_args))
 }
fn.toString = function(){
  return args.reduce((a,b)=>a+b)
}
return fn
}

这返回的是函数啊??

@orime
Copy link

orime commented Mar 1, 2021

单纯从题意触发,add调用时候必须有toString之类的触发条件;用外部变量保存每次执行累计的参数列表,执行完toString之后清空即可:

// * 柯理化函数
let concatArgs = []
function add(...args) {
  concatArgs = concatArgs.concat(args)
  return add
}
add.toString = function () {
  const res = concatArgs.reduce((pre, cur) => pre + cur, 0)
  concatArgs = []
  return res
}

console.log(add(1)(2)(3) + "") // 6
console.log(add(1)(2, 3) + "") // 6
console.log(add(1, 2)(3) + "") // 6
console.log(add(1, 2, 3) + "") // 6
console.log(add(1).toString()) // 1
console.log(add(1)(2).toString()) // 3
console.log(add(1)(2)(3).toString()) // 6
console.log(add(1)(2, 3).toString()) // 6
console.log(add(1, 2)(3).toString()) // 6
console.log(add(1, 2, 3).toString()) // 6

@WayneGongCN
Copy link

题目不严谨,有歧义。

在实际项目中如果有这样的需求,或者用 toString 这种 hack 的方式实现。

感谢同事不杀之恩吧。

const money = add(1)(2)
typeof money  // function
// 同事:“... wtf ?”


const money = add(1)(2)
if (money < 100) money(3)
// 同事:“???”


const money = add(1)(2)
console.log(money)  // f 3
// 此处省略 100+ 行代码...
console.log(money)  // money:“猜猜我变没变”

// ...卒

@dengbupapapa
Copy link

function add(...args) {
    if (Number.prototype.add !== add) Number.prototype.add = add;
    return args.reduce(
        (pre, now) => pre + now,
        this instanceof Number ? this : 0
    );
}

修改Number满足吗

@crush12132
Copy link

let timer = null
function add(...arg1){
	return function(...arg2){
		let arg = [...arg1,...arg2]
		clearTimeout(timer)
		timer = setTimeout(()=>{
			console.log(arg.reduce((p,c)=>p+c))
		},0)
		return add(...arg);
	}
}

add(2,3)(4)(5,6)(9)()(1) //30

但是这个好像不能执行add(1,2,3)这种

@slc3a2
Copy link

slc3a2 commented Apr 30, 2021

做一个可循环调用add函数,执行时把arg1arg2内外传入的两个参数加到一块。函数的toString方法在函数被alert或者console的时候会被调用,可以用这个方法来确定是否需要输出总结果。

function add (...arg1) {
  let t = function (...arg2) {
    return add(Array.from(arg1).concat(Array.from(arg2)).reduce((a, b)=> {return a+b}))
  }
  t.toString = ()=>{
    return Array.from(arg1).reduce((a, b)=> {return a+b})
  }
  return t
}

@zhelingwang
Copy link

zhelingwang commented May 10, 2021

add(1); 	// 1
add(1)(2);  // 3
add(1)(2)(3); // 6
add(1)(2, 3); // 6
add(1, 2)(3); // 6
add(1, 2, 3); // 6
function add(...args) {
  let final = [...args];
  setTimeout(() => {
    console.log(final.reduce((sum, cur) => sum + cur));
  }, 0);
  const inner = function (...args) {
    final = [...final, ...args];
    return inner;
  }
  return inner;
}

@tianfengbiao
Copy link

function add() {
var a = 0;
var out = arguments;

function sum() {
    for(var i = 0; i < arguments.length; i++) {
        a += arguments[i]
    }
    return sum
}

sum.toString = function() {
    for(var i = 0; i < out.length; i++) {
        a += out[i]
    }
    return a;
}

return sum;

}

@qinyakang
Copy link

qinyakang commented Sep 2, 2021

const add=(a,b,c)=>a+b+c
    const currying=(fn,length)=>{
        length=length||fn.length
        return (...args)=>args.length>=length?fn(...args):currying(fn.bind(this,...args),length-args.length)

    }
    const sum=currying(add)
    console.log(sum(1)(2)(3));
    console.log(sum(1,2)(3));
    console.log(sum(1)(2,3));
    console.log(sum(1,2,3));

@qinyakang
Copy link

qinyakang commented Sep 2, 2021

function add() {
  let args = [].slice.call(arguments);
  let fn = function(){
   let fn_args = [].slice.call(arguments)
   return add.apply(null,args.concat(fn_args))
 }
fn.toString = function(){
  return args.reduce((a,b)=>a+b)
}
return fn
}
const add=(...args)=>{
        const fn=(...params)=>add(...args,...params)
        fn.toString=()=>args.reduce((a,b)=>a+b)
        return fn
    }
    console.log(add(1,2)(3).toString());

@SH-dxj-SF
Copy link

function add(...args) {
  let nums = [...args];

  function _add(...argsNext) {
    if (argsNext.length === 0) {
      // 不再有参数传入作为计算结果的信号
      return nums.reduce((pre, cur) => {
        return pre + cur;
      }, 0);
    } else {
      nums.push(...argsNext);
      return _add;
    }
  }

  return _add;
}

@xiangfei1
Copy link

xiangfei1 commented Oct 21, 2021

function add(...a){
   let sum = (...b) => add(...[...a,...b]);  //合并参数
   let result = a.reduce((x,y) => x+y);  //对所有参数进行累加
   sum.toString = () => result;  //将结果返回
   return sum;
}
console.log(add(1,2,3)(2,2).toString());  //10

@z547224313
Copy link

为什么console的时候不会自动调用 toString方法呢,上面的答案在我的chrome控制台里返回的都是函数

@virgo-van
Copy link

function add(...args1) {
    let x = args1.reduce((c,r)=>{return c+r},0)
    console.log(x)
    return  function(...args2){
            return add(...args2,x);
    };
}
add(1,2)(2)(1,3,4)

可以实现连续不定参数的调用,返回参数和

@zhangtaolei
Copy link

zhangtaolei commented Nov 20, 2021

function add () {
  let sum
  let arg = [].concat(...arguments)
  const fn = function () {
    arg = arg.concat(...arguments)
    sum = arg.reduce((pre, next) => pre + next)
    return fn
  }
  fn.toString = function () {
    return sum
  }
  return fn()
}
console.log('//' + add(1, 2)(3)()(4, 5, 6))

@SnailOwO
Copy link

SnailOwO commented Dec 23, 2021

 function addFn(...args) {
        return args.reduce((acc, cur) => acc + cur)
    }

    function currying(fn) {
        let args = []

        return function demo(...arg) {
            console.log(args);
            if (arg) {
                args = [...args, ...arg]
                return demo
            } else {
                return fn.apply(this, args)
            }
        }
    }

    const add = currying(addFn)
    console.log(add(1)(2)(3)());
    console.log(add(1)(2,3));

@yangfan-coder
Copy link


 var twoSum = function(nums, target) {
    const map = {}

    for (let i = 0 ;i < nums.length; i ++ ){
        if(map[target - nums[i] ] >= 0) {
            return [map[target - nums[i]],i]
        }
        map[nums[i]] = i;   
    }
};

@CHristopherkeith
Copy link

为什么console的时候不会自动调用 toString方法呢,上面的答案在我的chrome控制台里返回的都是函数

我也遇到了类似的问题,toString的方案在新版的Chrome(我的版本是98)似乎不起作用,打印出来的是一个函数,需要显式调用才能返回结果

@Lingdeqing
Copy link

function add(a) {
    var curSum = a;
    function res(b) {
        curSum += b
        return res
    }
    res.toString = function () {
        return curSum
    }
    return res
}

@chengfengfengwang
Copy link

建议把题目描述清楚

@CHENJIAMIAN
Copy link

sum = (...nums)=>{
    let res = 0;
    sum2 = (...nums2)=>{
        res = nums2.reduce((acc,cur)=>acc + cur, res);
        console.log(res)
        return sum2;
    }
    return sum2(...nums)
}

//   实现 sum 函数
//sum(1)(2)(3)
//== 6; // true
//sum(1, 2, 3) //== 6; // true

// sum(1); 	// 1
// sum(1)(2);  	// 3
// sum(1)(2)(3)  // 6
// sum(1)(2, 3)   // 6
// sum(1, 2)(3)   // 6
// sum(1, 2, 3)   // 6

@xuxin666666
Copy link

如果只是打印结果不返回值的话,用个宏任务

function add() {
    let sum = {current: 0}
    sum.current = [...arguments].reduce((a, b) => a + b)

    setTimeout(() => {
        console.log(sum.current)
    })
    
    function _add() {
        sum.current += [...arguments].reduce((a, b) => a + b)
        return _add
    }
    return _add
}

add(1, 2)(3, 4)(5)
add(1)(2)(3)(4, 5, 6)
add(1, 2, 3)

上面那些toString的都是隐式调用的,结果拼接个字符串,或者非全等比较,就这样

add(1, 2)(3) + ''
add(1, 2)(3) == 6

@XieTongXue
Copy link

题目有让你们调用toString?个个在这乱抄,就不会运行一下?

@DevinXian
Copy link

题目有让你们调用toString?个个在这乱抄,就不会运行一下?

这位同学,不必用这种口气说话

@qifengla
Copy link

function add(...args) {
  const fn = (...newArgs) => add(...args, ...newArgs);
  fn.valueOf = () => args.reduce((acc, curr) => acc + curr, 0);
  return fn;
}

@88wixi
Copy link

88wixi commented Jul 24, 2023

function add(){
let sum = 0
function innerAdd(...args){
if(args.length===0){
return sum;
}
sum+=args.reduce((a,b)=>a+b,0)
return innerAdd;
}
return innerAdd(...arguments)
}

@G-WangZH
Copy link

// 函数求和
function sumFn(...rest) {
    return rest.reduce((a, b) => a + b);
}
// 柯里化函数
var currying = function (func) {
    // 保存所有传递的参数
    const args = [];
    return function result(...rest) {
        // 最后一步没有传递参数,如下例子
        if(rest.length === 0) {
            return func(...args);
        } else {
            // 中间过程将参数push到args
            args.push(...rest);
            return result; // 链式调用
        }
    }
}
// 测试
currying(sumFn)(1)(2)(3)(4)(); // 10
currying(sumFn)(1, 2, 3)(4)(); // 10

@negativeentropy9
Copy link

function curry(fn, acc, initValue) {
  let args = [];

  fun.toString = function () {
    if (args.length === fn.length) {
      return fn.apply(this, args);
    }

    const result = args.reduce(acc, initValue);

    args = [];

    return result;
  };

  return fun;

  function fun() {
    let result = fun;

    args = args.concat([...arguments]);

    if (args.length === fn.length) {
      result = fn.apply(this, args);
      args = [];
    }

    return result;
  }
}

var add = curry(
  (a, b, c) => {
    return a + b + c;
  },
  (acc, a) => acc + a,
  0
);

console.log(add(1).toString()); // 1
console.log(add(1)(2).toString()); // 3
console.log(add(1)(2)(3)); // 6
console.log(add(1)(2, 3)); // 6
console.log(add(1, 2)(3)); // 6
console.log(add(1, 2, 3)); // 6

@qbao788
Copy link

qbao788 commented Sep 26, 2024

function add(){
     const sum = function(){
            sum.value += [...arguments].flat(Infinity).filter(e=>e).reduce((a,b)=>a+b,0);
            if(arguments.length)
                return sum;
            return sum.value;
        }
        sum.value = [...arguments].flat(Infinity).filter(e=>e).reduce((a,b)=>a+b,0);
        sum.toString = sum.valueOf = function (){
            return this.value;
        }
        return sum;
}
let res = add(1,5,6)(2,3,4)(7)(8)(9)(10);
console.log(res.value,res(),res)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests