Skip to content

函数柯理化

概念

函数柯里化(Currying)是一种编程技术,又称部分求值(Partial Evaluation)。它将一个多参数函数转换成一系列接受单个参数的函数,每次调用返回一个新的函数,直到接收完所有必需的参数后才执行原始函数并返回最终结果。这样做的好处包括:可以更灵活地处理参数、创建特定用途的函数工厂以及更容易实现函数组合。

函数柯理化的基础是闭包

实现

js
function curry(fn) {
  return function judge(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args)
    } else {
      return function (...subArgs) {
        return judge.apply(this, args.concat(subArgs))
      }
    }
  }
}

// 一行代码实现
const currying = fn => (judge = (...args) => (args.length >= fn.length ? fn(...args) : (...subArgs) => judge(...args.concat(subArgs))))

// 测试
function sum(a, b, c) {
  return a + b + c
}

let currySum = curry(sum)

console.log(currySum(1, 2, 3)) // 6,仍然可以被正常调用
console.log(currySum(1)(2, 3)) // 6,对第一个参数的柯里化
console.log(currySum(1)(2)(3)) // 6,全柯里化

应用案例

在提交用户信息的时候校验手机号、邮箱

  • 校验函数封装
js
// 非柯里化版本
function checkByRegExp(regExp,string) {
  return regExp.test(string)
}

checkByRegExp(/^1\d{10}$/, '15010001000') // 校验电话号码
checkByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'test@163.com') // 校验邮箱

在实际使用中,不需要去关注正则是如何匹配的,只需要使用更具体函数去分别校验手机号或者邮箱,这里就需要使用柯里化函数处理:

js
// 进行柯里化
let _check = curry(checkByRegExp)
// 生成工具函数,验证电话号码
let checkCellPhone = _check(/^1\d{10}$/)
// 生成工具函数,验证邮箱
let checkEmail = _check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/)

checkCellPhone('18642838455') // 校验电话号码
checkCellPhone('13109840560') // 校验电话号码
checkCellPhone('13204061212') // 校验电话号码

checkEmail('test@163.com') // 校验邮箱
checkEmail('test@qq.com') // 校验邮箱
checkEmail('test@gmail.com') // 校验邮箱