什么是柯里化
当我们这个函数有多个参数的时候,我们可以对这个函数做一个改造,我们可以调用一个函数,值传递部分的参数,并且让这个函数返回一个新的函数,新的函数去接受剩余的函数,并且返回相应的结果,这就是函数的柯里化
- 示例
// 使用柯里化解决纯函数的硬编码
// 硬编码
function checkAge (age) {
let mini = 18;
return age >= mini;
};
// 普通的纯函数
function checkAge(age,mini) {
return mini >= age;
}
console.log(checkAge(18,24))
console.log(checkAge(18,26))
console.log(checkAge(24,28))
// 柯里化
function checkAge(age){
return function (mini) {
return mini >= age;
}
}
// ES6箭头函数
let checkAge = age => (mini => mini >= age)
let age18 = checkAge(18);
let age24 = checkAge(24);
console.log(age18(24))
console.log(age18(26))
console.log(age24(28))
刚刚演示的案例特别简单,不够通用,它只可以为checkAge服务,我们之前在演示纯函数的好处时,我们通过Lodash中的memoize
演示过纯函数可缓存性,下一节我们来学习如何通过Lodash使函数转化为柯里化函数
Lodash中的柯里化函数
- _.curry
- 功能:创建一个函数,该函数接收一个或者多个func的参数,如果func所需要的参数都被提供则执行func并返回执行的结果,否则继续返回该函数并等待接收剩余的参数。
- 参数:需要柯里化的函数
- 返回值:柯里化后的函数
- 只看文字时不够直观的,我们通过下列代码来了解curry方法
// lodash 中的 curry 基本使用
const _ = require("lodash")
// 函数有几个参数就是几元函数,如下列函数就是三元函数,柯里化能帮我们转化为一元函数
function getSum (n1, n2, n3) {
return n1 + n2 + n3
}
// 调用柯里化方法
const curried = _.curry(getSum);
console.log(curried(1, 2, 3))
console.log(curried(1)(2, 3))
console.log(curried(1, 2)(3))
柯里化案例
const _ = require('lodash')
const match = _.curry(function (reg, str) {
return str.match(reg)
})
const haveSpace = match(/\s+/g)
// console.log(haveSpace('helloworld'))
const filter = _.curry(function (func, array) {
return array.filter(func)
})
console.log(filter(haveSpace, ['john connor', 'john_donne']))
柯里化原理模拟
function curry (func) {
return function curriedFn (...args) {
// 实际参数的个数小于形式参数 --- console.log(curried(1)(2,3)); console.log(curried(1,2)(3))
if(args.length < func.length){
return function () {
/**
* args第一次调用时的参数
* arguments第二次的参数,因为他是伪数组,所以需要将它转成数组
* 通过concat将两次参数合并后得到一个数组,所以需要...将其传入函数
* */
return curriedFn (...args.concat(Array.from(arguments)))
}
}
/**
* 实际参数的个数大于等于形式参数的个数 --- console.log(curried(1,2,3))
* 调用时需要传递参数,这里的...agrs其实是一个数组,我们将数组作为参数传递给函数时有两种方法
* 1. apply
* 2. ...
* */
return func(...args)
}
}
function getSum (a,b,c) {
return a + b + c
}
const curried = curry(getSum)
console.log(curried(1,2,3))
console.log(curried(1)(2,3))
console.log(curried(1,2)(3))
总结
- 柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数
- 这是一种对函数参数的缓存
- 让函数变得更灵活,让函数的粒度更小
- 可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能