-
第一道菜
实现:
console.log(sum(1)(2)(3)) // 6
console.log(sum(1)(5)) // 6
console.log(sum(1)(2)(3)(4)) // 10
其实思想非常之简单
- 我们需要找办法收集好所有参数
- 收集完成后,触发某个事情把所有参数相加
function sum() {
let arg = [...arguments]; // 开始收集第一个圆括号内的参数,放到arg中
const fn = function() { // 收集函数
arg.push(...arguments)
return fn
}
fn.toString = function() { // 重写toString函数
let result = arg.reduce((acc, val) => {
return acc + val;
}, 0)
return result
}
return fn
}
我们举个例子 首先sum(1)(2)(3)
- 进去以后先执行的是sum(1),arg现在是[1],然后会return fn函数 也就是把收集函数返回了,这个收集函数的tostring方法被改写了。 arg.push(...arguments),
- 此时是变成了fn(2)(3),我们可以看看fn的函数定义,发现他可以处理2这个参数,现在执行arg.push(...arguments),arg变成了[1, 2]了,并且将自己导了出去。
- 接着fn(3),还是像上面那步一样,导入参数变成了(1, 2, 3)了,并且fn导了出去。此时console出现,执行fn的tostring方法,返回result。
影流之主的分割线。。。。。。。。。。。。。。。。。。。
-
第二道菜
// 不借助toString,需要求值计算,参数有所限制
console.log(sumAll(1)(2)(3)) // 6
console.log(sumAll(1)(2, 3)) // 6
以下是具体实现
function sum(a,b,c){
return a+b+c;
}
function curry(fn){
const args = [...arguments].slice(1);
return function(){
const newArgs = args.concat([...arguments])
if(newArgs.length<fn.length){
return curry.apply(this,[fn,...newArgs])
}else{
return fn.apply(this,newArgs)
}
}
}
const sumAll = curry(sum)
首先,将sum传进去,我们需要知道一点fn.length用来计算参数的长度,像sum,三个参数,便是3.
本质上和上一个算法是没什么区别的,都是先收集参数,再触发求值的流程。
- 首先sum先传入到了curry内,arg此时为[], 返回了一个函数。sumAll开始接受参数了,第一个接受的参数为1,newArg便是[1],发现newArg的参数收集只有1个,小于sum的长度(3),然后执行一次curry递归,将sum和新的参数收集放进去。
- 现在收集参数2,返回函数中,将2送入,此时的newArg是[1, 2]。
- 收集参数3,返回函数中,发现已经满足求值的条件了,触发sum的求值函数,返回1 + 2 + 3 = 6