函数柯里化指的是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。
作用:可以参数复用(公共的参数已经通过柯里化预置了)和延迟执行(柯里化时只是返回一个预置参数的新函数,并没有立刻执行,在满足条件后才会执行)。
参数定长的柯里化
思路:通过函数的length属性获取函数的形参个数,形参的个数就是所需参数的个数。维护一个数组,当数组的长度与函数接收参数的个数一致,再执行该函数。
// 实现函数柯里化
function curry(fn) {
// 返回一个新函数
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args); // 如果参数够了,就执行原函数,返回结果
} else {
//返回一个新函数,继续递归去进行柯里化,利用闭包,将当前已经传入的参数保存下来
return function (...args2) {
//递归调用 curried 函数
return curried.apply(this, [...args, ...args2]); //新函数调用时会继续传参,拼接参数
};
}
};
}
// 测试
function sum(a, b, c) {
return a + b + c;
}
var curried = curry(sum);
console.log(curried(1, 2, 3)); //6
console.log(curried(1, 2)(3)); //6
console.log(curried(1)(2, 3)); //6
console.log(curried(1)(2)(3)); //6
参数不定长的柯里化
思路:利用闭包和递归,如果参数为空,则判断递归结束,求和,返回结果。
function addCurry() {
// 利用闭包的特性收集所有参数值
let arr = [...arguments]
//返回函数
return function fn() {
// 如果参数为空,则判断递归结束,即传入一个()执行函数
if(arguments.length === 0) {
return arr.reduce((a, b) => a + b) // 求和
} else {
arr.push(...arguments)
return fn //递归
}
}
}
// 测试
console.log(addCurry(1)()); //1
console.log(addCurry(1)(2)()); //3
console.log(addCurry(1)(2)(3)()); //6
console.log(addCurry(1, 2)(3)()); //6
console.log(addCurry(1, 2, 3)()); //6