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

  1. //柯里化演示
  2. function checkAge (age) {
  3. let min = 18
  4. return age >= min
  5. }
  6. //普通的纯函数
  7. function checkAge (min, age) {
  8. return age >= min
  9. }
  10. console.log(checkAge(18, 20))
  11. console.log(checkAge(18, 24))
  12. console.log(checkAge(22, 24))
  13. //函数的柯里化
  14. function checkAge (min) {
  15. return function (age) {
  16. return age >= min
  17. }
  18. }
  19. // 函数柯里化->箭头函数写法
  20. let checkAge = min => (age => age >= min)
  21. let checkAge18 = checkAge(18)
  22. let checkAge20 = checkAge(20)
  23. console.log(checkAge18(20))
  24. console.log(checkAge18(24))

lodash的柯里化方法curry

.curry(func)

  1. // lodash 中的 curry 基本使用
  2. const _ = require('lodash')
  3. function getSum (a, b, c) {
  4. return a + b + c
  5. }
  6. const curried = _.curry(getSum)
  7. console.log(curried(1, 2, 3))
  8. console.log(curried(1)(2, 3))
  9. console.log(curried(1, 2)(3))

curry的使用案例

用curry生成一个更灵活的match函数。

一般纯函数实现:

  1. function match(reg, str) {
  2. return str.match(reg)
  3. }

一般纯函数的缺点是,如果经常使用的话,正则表达式可能重复。柯里化处理可以避免:

  1. const _ = require('lodash')
  2. const match = _.curry(function (reg, str) {
  3. return str.match(reg)
  4. })
  5. const haveSpace = match(/\s+/g)
  6. const haveNumber = match(/\d+/g)
  7. console.log(haveSpace('helloworld'))
  8. console.log(haveNumber('abc'))

用柯里化的match函数,定义了两个新的函数,haveSpace是查找空白字符,haveNumber是查找数字。有了这两个函数,那么match就不用每次都传入两个参数,函数粒度更小。另外,还可以实现功能更复杂的函数。

  1. const filter = _.curry(function (func, array) {
  2. return array.filter(func)
  3. })
  4. const findSpace = filter(haveSpace)
  5. console.log(filter(haveSpace, ['John Connor', 'John_Donne']))
  6. console.log(findSpace(['John Connor', 'John_Donne']))

filter函数实现了过滤功能,当需要查找数组中具有空白字符的字符串,又可以重复使用haveSpace这个函数。

柯里化函数每次传入一个参数,都会生成一个新的具有特定功能的函数。

lodash的curry方法实现

  1. function getSum (a, b, c) {
  2. return a + b + c
  3. }
  4. const curried = curry(getSum)
  5. console.log(curried(1, 2, 3))
  6. console.log(curried(1)(2, 3))
  7. console.log(curried(1, 2)(3))
  8. function curry (func) {
  9. return function curriedFn(...args) {
  10. // 判断实参和形参的个数
  11. if (args.length < func.length) {
  12. return function () {
  13. return curriedFn(...args.concat(Array.from(arguments)))
  14. }
  15. }
  16. return func(...args)
  17. }
  18. }

curry接收一个函数,并生成一个新的函数。传入curry的函数需要接受实际参数,而且传入的实际参数个数不固定,这时应该使用剩余参数(…args)去接收。并且需要判断形参和实参的个数是否相同。如果相同或实参个数大于相残,把args并传给func,展开直接执行func函数。如果实参个数小于形参个数,那么返回一个新的函数。在curriedFn函数内部,会形成闭包,curried内部的匿名函数可以访问args,并且匿名函数通过arguments获取新的实参,和args拼接后形成新的实参数组递归传入curriedFn

总结

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