JavaScript中的函数式编程--柯里化

209 阅读2分钟

柯里化(Curry)

什么是柯里化:

  • 可以将任意多参数的函数转化成单参数的函数
    • 当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数以后永远不变)
    • 然后返回一个新的函数接收剩余参数并返回结果

使用柯里化可以解决上边提到的硬编码的问题 示例:年龄检测

    // 硬编码
    function checkAge(age) {
        let mini = 18 // 编成局部变量
        return age >= mini
    }
    
    // 普通的纯函数解决硬编码(将mini提取到参数位置)
    function checkAge(min, age) {
        return age >= min
    }
    
    // 上边的普通纯函数会遇到之前在闭包中说过的重复输入的问题
    // 解决:函数的柯里化
    function checkAge(min) {
        return function(age) {
            return age >= min
        }
    }
    // 年龄基准值18
    let checkAge18= checkAge(18)
    console.log(checkAge18(20))
    // 年龄基准值20
    let checkAge20= checkAge(20)
    console.log(checkAge20(22))
    // 以上就是简单的函数柯里化
    // 当我们函数有多个参数的时候对其进行改造
    // 在调用一个函数的时候只传递部分参数,然后返回新的函数
    // 新的函数接收剩余参数,并返回结果
    
    // 柯里化后的checkAge使用ES6简化
    let checkAge = min => (age => age >= min)

Lodash中的柯里化

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

示例:lodash中curry方法使用

    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))

柯里化案例

匹配数组中具有空字符串的字符

    const _ = require('lodash')
    // 匹配规则
    const hasSpace = match(/\s+/g)
    // ES5
    const filter = _.curry(function (func, array) {
        return array.filter(func)
    })
    // ES6
    const filter = _.curry((func, array) => array.filter(func))
    console.log(filter(hasSpace, ['John Connor', 'John_Donne']))
    // => ['John Connor']

柯里化原则模拟(实现原理)

示例:

    // 函数柯里化:一个函数接收一个函数参数,返回一个新的函数
    function getSum(a, b, c) {
        return a + b + c
    }
    function curry(fn) {
        return function curriedFn(...args) {
            if (args.length < fn.length) {
                return function() {
                    return curried(...args.concat(Array.from(arguments)))
                }
            } 
            return fn(...args)
        }
    }
    const curried = curry(getSum)
    console.log(curried(1, 2, 3))
    console.log(curried(1)(2, 3))
    console.log(curried(1, 2)(3))

柯里化总结

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