柯里化

一. 什么是柯里化?

当一个函数有多个参数的时候,我们可以对函数进行改造。让其只传入一部分参数并调用它(这部分参数以后永远不变),
然后返回一个新的函数接收剩余参数,并返回相应的结果。
柯里化最终会帮我们把任意多参数的函数转化为一个一元函数。

?:

  function checkAge (min) {
    return function(age) {
      return min > = age
    }
  }
  
 let checkAge18 = checkAge(18);
 let checkAge20 = checkAge(20);
 
 checkAge18(20)
 checkAge20(44)
  
复制代码
二. Lodash中通用的柯里化方法

参考: _.curry

  • 功能: 创建一个函数,该函数接收 func 的参数。
    如果 func所需参数已经提供,则执行fun并返回执行的结果。
    否则继续返回该函数并等待接收剩余的参数。
  • 参数: 需要柯里化的函数
  • 返回值:柯里化后的函数
var abc = function(a, b, c) {
  return a +  b + c;
};
 
var curried = _.curry(abc);
 
curried(1)(2)(3);
// => 6
 
curried(1, 2)(3);
// =>6
 
curried(1, 2, 3);
// => 6
 
复制代码
三. 柯里化案例
  • 提取字符串中的空白字符或者数字
//可能用到的正则表达式
''.match(/\s+/g) //空白字符
''.match(/\d+/g) //数字
复制代码

实现:

//思路: 要实现上述需求我们需要两个参数,
    // 第一☝️: 匹配的正则, 第二:哪个字符串
import { curry } from 'lodash';
// 使用curry 对我们的函数进行包装
const match = curry(function (reg, str) {
  return str.match(reg);
});

//接着我们一起来看下测试结果:
const haveSpace = match(/\s+/g);
console.log(haveSpace('hello world')); // [" "]
console.log(haveSpace('helloworld')); // null

const haveNumber = match(/\d+/g);
console.log(haveNumber('hello world123')); // ["123"]
console.log(haveSpace('helloworld')); // null
复制代码
  • 对数组进行过滤
// 如果要进行过滤, 我们需要两个参数,
//  第一☝️: 怎么过滤, 第二: 哪个数组
const filter = curry((handleFilter, arr) => arr.filter(handleFilter));

//看测试结果:
 console.log(filter(haveSpace, ['LiLei', 'Han Meimei'])); //["Han Meimei"]

const findSpace = filter(haveSpace);
console.log(findSpace(['LiLei', 'Han Meimei'])); //["Han Meimei"]
复制代码

总结:使用柯里化我们可以最大程度的重用我们的函数,比如上面的haveSpace, haveNumber等。

四. 模拟柯里化的实现

我们先思考下lodash中的curry的调用形式。

    //它接收一个参数,且是一个函数,这个函数是要被柯里化处理的函数。
    //并且要返回一个纯函数
    //那么我们来定义自己的柯里化函数
    function myCurry(func) {
        return curriedFn() {
        }
    }
复制代码

然后再使用时比较实参和形参的个数

  • 如果传递了全部参数,那么立即调用,并返回执行结果
  • 只传递所需参数的部分参数,返回一个新的函数,等待接受剩余参数

具体代码实现如下:

function myCurry(func) {
    //返回一个柯里化后的函数
    return function curriedFn(...args) {
    //按照以上思路对比实参和形参的个数
    // 实参 => args.length
    // 形参 => func 的参数个数
    // 如果实参 < 形参的个数,返回柯里化函数,注意参数的合并
        if (args.length < func.length) {
          return function () {
            return curriedFn(...args.concat(Array.from(arguments)));
          };
        }
        // 立即调用,并返回执行结果
        return func(...args);
    };
}
复制代码

最后我们来测试下自己的柯里化函数

function getSum(a, b, c) {
  return a + b + c;
}

const curried = myCurry(getSum);
console.log(curried(1)(2)(3));
console.log(curried(1, 2)(3));
console.log(curried(1, 2, 3));
复制代码
总结

最后一起来总结下柯里化的特性和优点吧~

  • 让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的函数。
  • 这是一种对函数的缓存。
  • 让函数变得更灵活,让函数的粒度变得更小。
  • 可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能。
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享