什么是函数柯里化?
函数有多个参数,调用函数时先传递部分参数,并返回一个新的函数接收剩余的参数,返回相应的结果
// 硬编码
function checkAge(age) {
let mini = 18;
return age >= mini;
}
// 普通的纯函数
function checkAge(mini, age) {
return age >= mini;
}
// 柯里化实现
function checkAge(mini) {
return function(age) {
return age >= mini;
}
}
let checkAge18 = checkAge(18);
let checkAge22 = checkAge(22);
console.log(checkAge18(19)); // true
console.log(checkAge22(19)); // false
lodash中的柯里化函数 _curry(func)
功能:创建一个函数,该函数接收一个或者多个func的参数,如果func所需要的参数都被提供则执行func返回执行结果,否则继续返回该函数并等待接收剩余的参数
- 参数:需要柯里化的函数
- 返回值:柯里化后的函数
柯里化最终将我们的多元函数转换为一元函数(有几个传参就是几元函数)
function getSum(a, b, c) {
return a + b + c;
}
const CurryFunc = _.curry(getSum);
console.log(CurryFunc(1, 2)(3)); // 6
console.log(CurryFunc(1)(2)(3)); // 6
console.log(CurryFunc(1)(2, 3)); // 6
柯里化案例
- 提取字符串中的空白字符、数字 .match(/\s+/g) .match(/\d+/g)
- 函数式编程:提高代码的的复用性
// 实现查找str是否满足正则reg
let match = _.curry(function (reg, str) {
return str.match(reg);
});
const hasSpace = match(/\s+/g);
const hasnumber = match(/\d+/g);
console.log(hasSpace('hello world! ')); // true
console.log(hasnumber('123hello world! ')); // true
// 实现过滤
const myFilter = _.curry(function(func, arr) {
return arr.filter(func);
})
const findSpace = myFilter(hasSpace);
console.log(findSpace(['hello kity', 'Sunny'])); // ['hello kity']
柯里化的实现原理
模拟lodash的curry实现 利用es6的rest参数
function myCurry(func) {
return function curriredFn(...args) {
// 判断形参和实参的个数,获取一个函数形参的个数可以通过「函数名.length」来获取
// 如果实参的个数小于形参的个数,那么返回一个函数用来处理剩余的参数,这个时候产生了闭包
if (args.length < func.length) {
return function () {
return curriredFn(...args.concat(Array.from(arguments)));
}
} else { // 否则执行传递的函数并返回其结果
return func(...args);
}
}
}
function getSum(a, b, c) {
return a + b + c;
}
const CurryFunc = myCurry(getSum);
console.log(CurryFunc(1, 2)(3)); // 6
console.log(CurryFunc(1)(2)(3)); // 6
console.log(CurryFunc(1)(2, 3)); // 6
函数柯里化总结
- 柯里化让我们给一个函数传递较少的参数得到一个已经记住的某些固定参数的新函数
- 对函数参数的缓存
- 使得函数更加灵活,粒度更小
- 可以把多元函数转换为一元函数,并使用函数组合得到功能更加强大的函数