• JS柯里化


    1 .柯里化的结构

    柯里化表现形式

    function add(x, y, z) {
      return x + y + z
    }
    var result = add(10, 20, 30)
    console.log(result)
    
    function sum1(x) {
      return function(y) {
        return function(z) {
          return x + y + z
        }
      }
    }
    var result1 = sum1(10)(20)(30)
    console.log(result1)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 简化柯里化代码
    // 简化柯里化的代码
    var sum2 = x => y => z => {
      return x + y + z
    }
    
    console.log(sum2(10)(20)(30))
    var sum3 = x => y => z => x + y + z
    console.log(sum3(10)(20)(30))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2. 让函数的职责单一

    为什么需要有柯里化呢?

    • 在函数式编程中,我们其实往往希望一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个函数来处理;
    • 柯里化函数可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果;

    案列需求

    • 第一个参数+ 2
    • 第二个参数* 2
    • 第三个参数** 2
      以前的实现方式
    function add(x, y, z) {
      x = x + 2
      y = y * 2
      z = z * z
      return x + y + z
    }
    console.log(add(10, 20, 30))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    柯里化实现方式

    function sum(x) {
      x = x + 2
      return function(y) {
        y = y * 2
        return function(z) {
          z = z * z
          return x + y + z
        }
      }
    }
    console.log(sum(10)(20)(30))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3 .柯里化的复用

    • 使用柯里化的场景是可以帮助我们复用参数逻辑

    需求假如在程序中,我们经常需要把5和另外一个数字进行相加
    以前的代码

    function sum(m, n) {
      return m + n
    }
    console.log(sum(5, 10))
    console.log(sum(5, 14))
    console.log(sum(5, 1100))
    console.log(sum(5, 555))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    柯里化后的代码实现功能

    • makeAdder函数要求我们传入一个num(并且如果我们需要的话,可以在这里对num进行一些修改);
    • 在之后使用返回的函数时,我们不需要再继续传入num了;
    function makeAdder(count) {
      count = count * count
    
      return function(num) {
        return count + num
      }
    }
    
    // var result = makeAdder(5)(10)
    // console.log(result)
    var adder5 = makeAdder(5)
    // 利用这样传值进行柯里化函数
    adder5(10)
    adder5(14)
    adder5(1100)
    adder5(555)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    4 .柯里化代码复用二

    需求是打印一些日志:

    • 日志包括时间类型信息

    普通函数的实现方案如下:
    在这里插入图片描述
    柯里化代码实现
    在这里插入图片描述

    function log(date, type, message) {
      console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`)
    }
    
    // log(new Date(), "DEBUG", "查找到轮播图的bug")
    // log(new Date(), "DEBUG", "查询菜单的bug")
    // log(new Date(), "DEBUG", "查询数据的bug")
    
    // 柯里化的优化
    var log = date => type => message => {
      console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`)
    }
    
    // 如果我现在打印的都是当前时间
    var nowLog = log(new Date())
    nowLog("DEBUG")("查找到轮播图的bug")
    nowLog("FETURE")("新增了添加用户的功能")
    
    var nowAndDebugLog = log(new Date())("DEBUG")
    nowAndDebugLog("查找到轮播图的bug")
    nowAndDebugLog("查找到轮播图的bug")
    nowAndDebugLog("查找到轮播图的bug")
    nowAndDebugLog("查找到轮播图的bug")
    
    var nowAndFetureLog = log(new Date())("FETURE")
    nowAndFetureLog("添加新功能~")
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    5 .手写柯里化函数

    • 当我们有将多个普通的函数,转成柯里化函数:
      在这里插入图片描述
    // 柯里化函数的实现hyCurrying
    function hyCurrying(fn) {
      function curried(...args) {
        // 判断当前已经接收的参数的个数, 可以参数本身需要接受的参数是否已经一致了
        // 1.当已经传入的参数 大于等于 需要的参数时, 就执行函数
        if (args.length >= fn.length) {
          // fn(...args)
          // fn.call(this, ...args)
          return fn.apply(this, args)
        } else {
          // 没有达到个数时, 需要返回一个新的函数, 继续来接收的参数
          function curried2(...args2) {
            // 接收到参数后, 需要递归调用curried来检查函数的个数是否达到
            return curried.apply(this, args.concat(args2))  //concat做拼接
          }
          return curried2
        }
      }
      return curried
    }
    
    var curryAdd = hyCurrying(add1)
    
    console.log(curryAdd(10, 20, 30))
    console.log(curryAdd(10, 20)(30))
    console.log(curryAdd(10)(20)(30))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    注意关于手写柯里化函数中的this

    在这里插入图片描述

    5 .1手写柯里化二

    //关键:使用数组存贮每次接受的参数 ,并返回新函数
    // 处理剩下的参数 ,知道最后在调用
    
    function  currying(fn,...args){
      //定义参数列表
      let len=fn.length;
      //判断是否为最后一个参数组
      //如果是,就递归调用
      if (args.length>=len) {
        return fn(...args)
        
      }
      //如果是.则把接收的参数拼接成数组
      return function(){
        let _args=args.concat([...arguments])
        return currying.call(this,fn,..._args)
      }
    }
    
    let add = currying()
    add(20)(30)(40)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    6 .组合函数

    • 组合(Compose)函数是在JavaScript开发过程中一种对函数的使用技巧、模式:
      • 比如我们现在需要对某一个数据进行函数的调用,执行两个函数fn1和fn2,这两个函数是依次执行的;
      • 那么如果每次我们都需要进行两个函数的调用,操作上就会显得重复;
      • 那么是否可以将这两个函数组合起来,自动依次调用呢?
      • 这个过程就是对函数的组合,我们称之为组合函数(Compose Function);
    // 实现最简单的组合函数
    function composeFn(m, n) {
      return function(count) {
        return n(m(count))
      }
    }
    
    var newFn = composeFn(double, square)
    console.log(newFn(10))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6 .1实现组合函数

    • 在传入了更多的函数,调用compose函数时,传入了更多的参数:
      在这里插入图片描述
    function hyCompose(...fns) {
      var length = fns.length
      for (var i = 0; i < length; i++) {
        if (typeof fns[i] !== 'function') {  //判断是否为函数
          throw new TypeError("Expected arguments are functions")   //抛出异常
        }
      }
      function compose(...args) {    //...args传入多个参数
        var index = 0     //先执行第一个参数
        var result = length ? fns[index].apply(this, args): args      //length 有长度的情况下 做调用  
        while(++index < length) {                            //利用while做循环    来进行拿到函数
          result = fns[index].call(this, result)               //[index]传递的是数组      利用call 传递的数组
        }
        return result
      }
      return compose
    }
    function double(m) {
      return m * 2
    }
    function square(n) {
      return n ** 2
    }
    
    var newFn = hyCompose(double, square)
    console.log(newFn(10))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    前端生成海报图:html2canvas 生成海报图
    node运行项目-Network: unavailable-没有ip地址
    工程数学笔记 | 傅里叶级数/变换的本质理解
    CSS - 盒子模型
    15分钟面试被5连CALL,你扛得住么?
    音视频技术在手机上的应用与挑战
    linux下使用vscode对C++项目进行编译
    如何让你赚钱的速度,像闪电一样?
    一文读懂什么是云原生|推荐收藏
    微信小程序 通过 pageScrollTo 滚动到界面指定位置
  • 原文地址:https://blog.csdn.net/weixin_46104934/article/details/126184737