柯里化的经典例子 : add(1,2,3,4,5) ----> finalAdd(1)(2)(3)(4)(5)
原函数
function add(num1, num2, num3, num4, num5) {
return num1 + num2 + num3 + num4 + num5
}
实现思路:
finalAdd(1) 返回的是一个函数..............finalAdd(1)(2) 返回的仍然是一个函数...............
可以得出finalAdd的大致框架:
function finalAdd() {
return function t() {}
}
我们可以很暴力的写出以下代码
function add(num1) {
return function(num2) {
return function(num3) {
return function(num4) {
return function(num5) {
return num1 + num2 + num3 + num4 + num5;
};
};
};
};
}
可以看到 finalAdd(1)(2)(3)(4)(5)就是不断递归返回的函数 ,递归结束的条件可以根据形参的个数来判断,对上述代码进行优化
function finalAdd(fn){
const len = fn.length // 传入fn的参数个数,根据这个个数来判断什么时候结束递归
return function t(){
const innerLength = arguments.length //传入实参的个数
const args = Array.prototype.slice.call(arguments) // 类数组---> 真实数组
if(innerLength >= len) {
return fn.apply(undefined,args)
}else{
const innerArgs = Array.prototype.slice.call(arguments) // 类数组---> 真实数组
const concatargs = args.concat(innerArgs)
return t.apply(undefined,concatargs)
}
}
}
这个函数finalAdd(1,2)(3)(4,5)也是可以的
如果不知道形参的个数呢,哪又该怎么办???
原始函数是这样的呢??
function add(...nums) {
return nums.reduce((sum, num) => sum + num)
}
这个时候就需要一个数据来记录累计传的参数,这里用数组来实现
function curryAdd(fn) {
// 累积参数的数组
let accumulatedArgs = []
// 定义一个内部函数,用于累积参数和计算结果
function curried(...args) {
// 将传入的参数加入累积参数数组
accumulatedArgs = [...accumulatedArgs, ...args]
// 返回一个新的函数,继续累积参数或计算结果
return function (...newArgs) {
if (newArgs.length === 0) {
// 如果没有传入新的参数,则计算结果并返回
const result = fn(...accumulatedArgs)
accumulatedArgs = [] // 记得重置数组哦
return result
} else {
// 否则继续累积参数
return curried(...newArgs)
}
}
}
// 返回初始的 curried 函数
return curried()
}
const curriedAdd = curryAdd(add)
// 调用示例
console.log(curriedAdd(1)(2)(3)(4)(5)()) // 输出 15
console.log(curriedAdd(10, 20)(30, 40)()) // 输出 100
console.log(curriedAdd(1)(2)(3)(4, 5)()) // 输出 15