什么是柯里化
当我们的函数有多个参数的时候,我们可以对这个函数进行改造,我们可以调 用一上函数只传递部分的函数,并且让这个函数返回一个新的函数,让这个函数去接受剩余的函数,并且返回相应的结果,这就是函数的柯里化。
普通的纯函数和柯里化的对比
//普通的纯函数
function checkAge(min, age) {
return age >= min;
}
console.log(checkAge(18,20));
console.log(checkAge(18,24));
console.log(checkAge(18,15));
//柯里化
function checkAge(min){
return function(age){
return age>=min;
}
}
let checkAge18=checkAge(18);
console.log(checkAge18(20));
console.log(checkAge18(24));
console.log(checkAge18(15));
lodash中的柯里化函数
_.curry(func)
- 功能:创建一个函数,该函数接收一个或多个func的参数,如果func所需要的参数都被提供则执行func并返回执行的结果,否则继续返回该函数并等待接收剩余的参数。
- 参数:需要柯里化的函数。
- 返回值:柯里化后的函数
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));
当我们调 用curried这个方法的时间,它会返回一个柯里化的函数,这个函数在调用的时候我们可以传递getSum所需的所有参数,当我们传了所有参数时会立即调用并且返回结果,如果curry在调 用的时候只传入部分参数,所以返回一个函数等待接受剩余的其他参数,最重要的一点是curried这个函数可以把任意的函数传换成一元函数
假如我们判断一个字符串中是否有空白字符或者我们要去提取字符串中的所有空白字符,那我们可以使用字符串的match方法,这是我们使用的面向过程的方式来提取字符串中的空白或者数字,那假如我们要提取数组中的空白的元素,那上面的代码就没有办法重用了。
const _ = require("lodash");
const match = _.curry(function (reg, str) {
return str.match(reg);
});
const haveSpace = match(/\s+/g);
const haveNumber = match(/\d+/g);
console.log(haveSpace('helloworld'));
console.log(haveNumber('abc1'))
我们可以使用函数式的方式,因为函数式的编程让我们最大限度的去重用函数。
接下来我们再思考一件事情,我们要过滤一个数组,找到数组中所有具有空白字符串的元素,这个时候该如何来写呢,那我们知道对数组进行过滤,我们可以调用数组的filter方法,那我们可以把数组的filter方法给封装成一个纯函数的形式
const _ = require("lodash");
const match = _.curry(function (reg, str) {
return str.match(reg);
});
const haveSpace = match(/\s+/g);
const haveNumber = match(/\d+/g);
const filter=_.curry(function(func,array){
return array.filter(func);
})
const findSpace = filter(haveSpace);
console.log(filter(haveSpace,['John Connor','John_Donne']));
console.log(findSpace(['John Connor','John_Donne']))
你可能觉得这样写起来非常的麻烦,我们还不如直接调 用match自己来实现呢,但是你要清楚一点的是,我们现在写的这些函数,将来可以不停的去重复使用的,这些函数我们只需要定义一次,将来可以重复的去使用
我们已经会调用lodash中的curry方法,那我们不光要会调 用,还要知道他内部的实现原理,我们来模拟一个lodash中的curry方法
function curry(func){
return function curriedFn(...args){
//判断实参和形参的个数
if(args.length<func.length){
return function(){
return curriedFn(...args.concat(Array.from(arguments)))
}
}
return func(...args);
}
}
柯里化可以让我们生成一个新的函数,并且我们生成的这个新的函数他已经记住了某些固定的参数。其实柯里化的内部就是使用了闭包,记住了我们给传递了部分入参,这是柯里化的核心
多元函数是指多个参数的函数,一元函数是只有一个参数的函数