接下来看函数式编程中另一个重要概念-----柯里化
柯里化
承接上文,副作用让checkAge函数变成不纯的函数,接下来我们把不纯的函数改造成纯函数。
很简单,把mini变量 放到函数内部,变成局部变量那他就变成一个纯的函数了
function checkAge (age) { //纯的,存在硬编码
let mini = 18;
return age >= mini;
};
checkAge(20); // true
mini = 28;
checkAge(20); // false
那这样又有一个问题,因为我们的mini变量等于一个具体的数组,就出现了硬编码。我们都知道,在写程序的时候要尽量避免硬编码。我们要解决硬编码也比较简单,只是需要把18提取到参数位置就可以了。
function checkAge (min,age) { //纯的,存在硬编码
return age >= mini;
};
checkAge(18,20); // true
checkAge(18,22); // true
checkAge(18,24); // true
这里我们就改造完了,我们根据输入始终会得到相同的输出,因为他不在依赖于外部的变量,并且它里面也没有硬编码。
可以发现,上面代码如果一直使用18这个基准值的时候,那么18这个值就会一直被重复,我们可以使用闭包的方法来解决这个问题,比如我们重新定义chekAge函数,它接收一个基准值min,返回一个函数。
返回的函数中接收一个age参数, 在函数体中我们返回age大于等于min,定义完之后,我们可以通过checkAge返回一个新的函数checkAge18,checkAge调用的时候就可以传入18。这个18就记录到了函数中。
function checkAge (mini) {
return function (age) {
return age >= mini;
}
}
let checkAge18 = checkAge(18);
checkAge18(20);
checkAge18(21);
checkAge18(22);
这里可以发现我们在调用的时候不会让基准值重复,因为我们在第一个函数中已经确定下来了。当然,上面例子比较简单,而且不够通用,因为这个柯里化函数只能为checkAge服务。
以上函数调用的方式就是柯里化,那我们这里简单说明一下什么是柯里化。
概念:·当一个函数有多个参数时我们可以对这个函数进行改造,让它先接受部分参数调用它(这部分参数永远不变)
然后 返回一个新的函数,这个新的函数去接收剩余的参数,并返回相应的结果,这就是函数的柯里化。
lodash中通用的柯里化方法(curry)
_.curry(fn):功能:创建返回一个函数,该函数接收一个或多个fn函数的参数,如果fn的参数被一次性提供,那么直接返回结果,否则继续返回该函数等待接收其他剩余参数。
参数:需要柯里化的函数
返回:柯里化后的函数
最终目的:柯里化可以把一个多元函数最终转化成一个一元函数(这对后面的函数组合是非常重要的)
const _ = require('lodash');
function getSum (a, b, c) {
return a + b + c;
}
const curried = _.curry(getSum);
// curried(1, 2, 3);
// curried(1)(2, 3);
curried(1, 2)(3);
来看一个案例,目标是根据不确定的正则匹配筛选某数组中符合条件的元素
const _ = require('lodash');
const match = _.curry(function(reg,str){
return str.match(reg);
});
const haveSpace = match(/\s+/g);
const haveNumber = match(/\d+/g);
let arr = ["curry30","lebron James","kobe brant24"];
let filter = _.curry(function(fn,arr){
return arr.filter(fn)
});
const filterSpace = filter(haveSpace);
const filterNumber = filter(haveNumber);
let endSpace = filterSpace(arr)
let endNumber = filterNumber(arr)
console.log(endSpace);
console.log(endNumber);
总结
柯里化可以让我们给一个函数传递较少的参数,得到一个记住这些固定参数的新函数。;
这是一种对函数参数的缓存(使用闭包缓存参数)
让函数变得更灵活,因为我们可以通过函数生成粒度更小的函数,函数组合时使用;(函数的粒度,即函数的代码量和功能量)
把多元函数转换成一元函数,把一元函数组合成功能更强大的函数;