概念
函数柯里化是指将一个多参数的函数转化成多个一个参数调用的函数的过程。
实现
柯里化的实现方式很多,如下:
//向函数传入两个用户
//输出问候
function say(user1, user2) {
return `hello ${user1} and hi ${user2}`;
}
console.log(say("Tom", "Tolly"));
//hello Tom and hi Tolly
//将其转化为两个一个参数的函数
function c(user1) {
return function (user2) {
return `hello ${user1} and hi ${user2}`;
}
}
let say2 = c("Tom");
console.log(say2("Tolly")); //c("Tom")("Tolly");
//hello Tom and hi Tolly
此时只有两个参数,但是如果有三个或者多个呢
//向函数传入三个参数
//输出问候
function say3(user1, user2, msg) {
return `hello ${user1} and hi ${user2}, 咳咳 ${msg}`;
}
console.log(say3("Tom", "Tolly", "嗯~"));
//hello Tom and hi Tolly, 咳咳 嗯~
//将其转化为两个一个参数的函数
function c3(user1) {
return function (user2) {
return function (msg) {
return `hello ${user1} and hi ${user2}, 咳咳 ${msg}`;
}
}
}
c3("Tom")("Tolly")("嗯~");
//hello Tom and hi Tolly, 咳咳 嗯~
很明显,如果参数很多,这种方式也不是一种很好的方式,而且每次都要对底层函数进行修改,所以接下来继续优化,写一个通用的柯里化函数。
// 这次我们来实现一个字符串相加的操作
const concatStr = (str1, str2, str3) => {
return str1 + str2 + str3;
}
// 通用柯里化
function currying (fn) {
const c_args = Array.prototype.slice.call(arguments, 1); //获取到除了被柯里化函数之外的参数
const fn_args_length = fn.length; //被柯里化的函数参数个数
return function () { //返回一个等待调用的函数
const f_args = Array.prototype.slice.call(arguments); //获取到被调用时传入的参数(转成数组)
const args = c_args.concat(f_args); // 将所有参数合并到一起
if (args.length < fn_args_length) {
args.unshift(fn);
return currying.apply(null, args);
} else {
return fn.apply(null, args);
}
}
}
//测试1
const str = currying(concatStr);
console.log( str("ab")("c")("def") ); // "abcdef"
console.log( str("ab", "c")("def") ); // "abcdef"
console.log( str("ab")("c", "def") ); // "abcdef"
console.log( str("ab", "c", "def") ); // "abcdef"
//测试2
const strAB = currying(concatStr, "ab");
console.log( strAB("c", "def") ); //"abcdef"
以上就完成了一个通用柯里化函数,会根据被柯里化函数的参数个数自动适配。