0
点赞
收藏
分享

微信扫一扫

04-柯里化(Haskell Brooks Curry)

夏侯居坤叶叔尘 2022-05-04 阅读 74
javascript

柯里化(Currying)

  • 当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数以后永远不变)
  • 然后返回一个新的函数接受剩余的参数,返回结果

  • 使用柯里化解决纯函数中一个硬编码问题
// 柯里化演示
// function checkAge(age){
//     // 把基准值定义成了一个数字,这是硬编码
//     let min = 18
//     return age >= min
// }

// 普通的纯函数
// function checkAge(min,age){
//     return age >= min
// }

// 18重复出现,处理
// console.log(checkAge(18,24));
// console.log(checkAge(18,24));
// console.log(checkAge(22,24));


// 函数柯里化
// function checkAge(min){
//   return function(age){
//       return age >= min
//   }
// }

// 使用ES6写柯里化
let checkAge = min => (age => age >= min)

// 判断是否为18的函数
let checkAge18 = checkAge(18)
let checkAge20 = checkAge(20)


console.log(checkAge18(22));
console.log(checkAge18(24));

lodash中的柯里化

  • _.curry(func)
    • 功能:创建一个函数,该函数接收一个或多个func的参数,如果func所需要的参数都被提供则执行func并返回执行结果。否则继续返回该函数并等待接收剩余的参数
    • 参数: 需要柯里化的函数
    • 返回值:柯里化后的函数
const _ = require('lodash')

// 需要柯里化的函数
function getSum(a, b, c) {
  return a + b + c;
}

// 柯里化后的函数
let curried = _.curry(getSum);

// 测试
// 如果传入函数所有的参数,会立即调用,返回结果
// 如果传入部分参数,则会等待剩余参数传入再执行
console.log(curried(1, 2, 3));
console.log(curried(1)(2)(3)); 
console.log(curried(1, 2)(3));

柯里化案例

// 柯里化案例
// ''.match(/\s+/g)  //全局匹配任意空白字符
// ''.match(/\d+/g)  // 匹配提权字符串中的数字

// 需要每次都传正则,我们将其柯里化
// function match(reg, str) {
//   return str.match(reg);
// }

let match = _.curry(function (reg, str) {
  return str.match(reg);
});

const haveSpace = match(/\s+/g)
const haveNumber = match('123abc')

// 没有会返回null
console.log(haveSpace("hello world"));//[' ']
console.log(haveNumber('12'));// null

// 柯里化这个函数,下面是直接调用和使用柯里化
const filter = _.curry(function(func,array){
    return array.filter(func)
})

// filter帮我们生成一个新的函数,我们只需要调用这个函数,传入测试的数组
const findSpace = filter(haveSpace) 

console.log(filter(haveSpace,['join aaa','aaaa'])); // [ 'join aaa' ]
console.log(findSpace(['join aaa','aaaa'])); //[ 'join aaa' ] 和之前一样

柯里化实现原理

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

// 原理
function curry(func) {
  return function curriedFn(...args) {
    // 判断实参和形成的个数
    if (args.length < func.length) {
      return function () {
        // 会缓存上一次传进来的args,和这次传进来的arguments合并
        // arguments是伪数组,需要转换成数组,再进行合并,展开
        return curriedFn(...args.concat(Array.from(arguments)));
      };
    }
    // 如果参数齐全,那么直接调用
    return func(...args);
  };
}

// 测试
let curryTest = curry(getSum)
console.log(curryTest(1, 2, 3)); // 会全部执行
console.log(curryTest(1)(2)(3));
console.log(curryTest(1, 2)(3));

总结

  • 柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数
  • 这是一种对函数参数的‘缓存’—闭包
  • 让函数变的更灵活,让函数的粒度更小
  • 可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能
举报

相关推荐

0 条评论