思考
一个函数有多个形参,可以传入多个实参。例如以下这段函数
js
function add(a,b,c){
return a+b+c;
}
我们是如何调用这个函数的?
js
add(1,2,3)//6
我们直接向函数中一次性传入三个形参,就像买东西一样,一次性付款,这样我们就成功地调用了add函数
但是如果我想分期付款呢?我将要传入的参数分3次分别传入,例如:
js
add(1)(2)(3)
我还要让这个函数被成功地调用起来,我们该如何实现???

开始
1. 构想
在动手写代码之前,我们先来构想一下,我们需要用到什么来完成我们的代码。
- Function.length
我们将多次传入参数,当我们传入足够的参数以后,才开始调用函数,所以我们究竟该怎么知道要传入几个参数呢?我们使用Function.length来获取
js
console.log(add.length)//3
- 闭包
我们是将参数分批传入函数的,所以我们还得在最后拿到我之前传入的参数,例如:
js
add(1)(2)(3)
当我传入(3)的时候,我必须还得拿到(1)(2),那么我们就得使用到闭包了...有不太懂闭包的掘友们可以去看我之前的文章(深入探讨:闭包的神秘面纱 - 掘金 (juejin.cn))
2.动手
参考上面的思路,我们来完成我们的代码
js
function curry(fn){
let judge = (...args)=>{
if(args.length === fn.length) return fn(...args) //退出条件
return (...arg) => judge(...args,...arg)
}
return judge
}
const curryAdd = curry(add)
console.log(curryAdd(1)(2)(3));
当我们调用 curry
函数并传入一个函数 fn
时,curry
函数会返回一个新的函数 judge
。这个 judge
函数可以接受任意数量的参数。
在 judge
函数内部,我们使用一个变量 args
来存储已经传入的参数。当我们调用 judge
函数并传入一些参数时,这些参数会被添加到 args
数组中。
然后,我们检查 args
数组的长度是否与原始函数 fn
的参数个数相等。如果相等,说明我们已经传入了所有需要的参数,此时我们直接调用原始函数 fn
并将 args
数组作为参数传递进去,并返回结果。
如果 args
数组的长度不等于 fn
的参数个数,那么我们就返回一个新的函数。这个新函数也是 judge
函数,并接受剩余的参数。我们使用扩展运算符 ...
将 args
数组和剩余的参数合并起来,并递归调用 judge
函数。这样就可以继续接受更多的参数,直到参数个数满足条件。
看结果:

收工
这个方法也叫函数的柯里化,函数柯里化是一种将多个参数的函数转化为一系列只接受单个参数的函数的过程。这种实现方式可以使函数变得更加灵活,可以逐步传递参数,使代码更易读和可维护。
