函数式编程 -- 柯里化
柯里化
-
当一个函数有多个参数的时候,先传递一部分参数调用它(这部分参数以后将不会再发生变化),然后返回一个新的函数接收剩余的参数,这个函数返回结果
-
示例
// _lodash 中的curry函数
const _ = require('lodash')
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))
//上面三种写都将得到一样的结果,即6
什么时候使用柯里化函数
比如在程序中,需要写很多遍同一函数、不同参数、同时我们又想保持函数的纯度的情况,可以采用柯里化简化参数,比如:
function checkAge(min,age){
return age>=min
}
checkAge(18,20)
checkAge(18,21)
checkAge(18,25)
checkAge(18,31)
// 上面这样,检测age是否>=min,对于需要写很多遍时,可以柯里化,像下面这样:
function checkAge(min){
return function(age){
return age >=min
}
}
//比较age是否>=18可以这样写:
let checkAge18=checkAge(18)
//比较age是否>=20可以这样写:
let checkAge20=checkAge(20)
//后续比较都只需要输入一个参数age就可以了
console.log(checkAge18(21))
console.log(checkAge20(21))
更多案例
匹配并获取字符串中的指定内容
const _ = require('lodash')
const match = _.curry(function(reg,str){
return str.match(reg)
})
const matchAndGetSpace = match(/\s+/g)
const matchAndGetNumber = match(/\d+/g)
console.log(matchAndGetSpace('sdf125sf ds 2ff sdf')
console.log(matchAndGetNumber('sdf125sf ds 2ff sdf')
柯里化原理模拟
fucntion curry(func){
return function curriedFn(...args){
// 判断实参和形参的个数
// 函数的长度即其参数的长度
if(args.length<func.length){
return function(){
// curriedFn接收散装参数,
// 而concat接收数组并返回数组
// arguments是伪数组,需要使用Array.from()来转化成数组
return curriedFn(...args.concat(Array.from(arguments)))
}
}
return func(...args)
}
}
function getSum(a,b,c){
return a+b+c
}
const curriedGetSum=curry(getSum)
console.log(curried(1,2,3))
console.log(curried(1,2)(3))
console.log(curried(1)(2,3))
总结
- 柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数
- 这是一种对函数参数的缓存
- 让函数变得更灵活,让函数的粒度更小
- 可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能