• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

【JS】函数式编程之组合函数

武飞扬头像
juejin
帮助32

前言

  • 什么是组合函数
  • 手写一个组合函数
  • 组合函数之结合律
  • 什么是pointfree
  • 调试组合函数

组合函数

顾名思义,组合函数是将多个函数按照排序进行执行,前一个函数返回的数据,作为下一个函数的参数,最后返回最终的结果。

例子

同样,我们看个例子,假使我们需要将一个数字先进行乘法运算,后进行求平方。我们会将这两个部分进行拆分成两个基础函数doublesquare。再通过double函数的返回值传入到square中调用。

image-20220124202712922

function double(num){
  return num*2
}

function square(num){
  return num**2
}

// 调用方式
const count=10
const res=square(double(count))
console.log(res);

柯里化和纯函数很容易写出可读性不强代码 square(double(count))

上面这种调用方式代码可读性不是很好,我们可以组合上面两个基础函数。

function composeFn(m,n){
  return function(count){
    return n(m(count))
  }
}

使用组合函数,将两个函数传入,composeFn会返回一个新的函数,我们只需要将要处理的数据传入到返回的这个新函数,这个新函数将会帮我们处理并返回处理好的数据。

const newFn=composeFn(double,square)
const res2=newFn(count)
console.log(res2);

通过compose组合而成的函数只能是一个参数,往往我们的基础函数参数可能不止一个,这时候我们将会用到柯里化函数进行处理。

关于柯里化,可以阅读这一篇文章【 聊一聊JavaScript中的柯里化

实现组合函数

function MyCompose(...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) {
    // 当前执行函数索引
    var index = 0;
    // 调用当前索引对应的函数
    var result = length ? fns[index].apply(this, args) : args;
    while (  index < length) {
      // 将上一次返回的结果,传入到下一个函数中
      var result = fns[index].call(this, result);
    }
    return result;
  }
  return compose;
}

解析写法

  1. 在一开始,函数接收一系列的函数。
  2. 先判断传入的参数是否全为函数,如果有一个非函数的函数则抛出异常
  3. 创建一个新函数,它需要接收要处理的参数
  4. 函数内,声明一个变量,记录当前执行的函数索引,将传入的参数按函数顺序执行
  5. 最终返回这个函数

结合律

结合律 (英文为 associativity),函数的组合要满足结合律,例如abc三个函数进行组合,可以将ab进行组合,或者是bc进行组合。这个特性计算结合律。

let fn = compose(a,b,c);
let ass1 = compose(compose(a,b),c);
let ass2 = compose(composea,(b,c));

pointfree

pointfree是一种编程风格,这种风格也被称之为Tacit programmingpoint代表形参,意思是没有形参的编程风格。

// pointfree风格,带有word形参
var word = (word) => word.toUpperCase();

// pointfree风格,没有任何形参
var word = compose(toUpperCase);

也就是说,我们完全可以把数据处理的过程,定义成一种与参数无关的合成运算。不需要用到代表数据的那个参数,只要把一些简单的运算步骤合成在一起即可。

它省去了对参数命名的麻烦,代码也更加简洁优雅。pointfree是基础函数的组合的高级函数,这些高级函数往往应用在我们的业务中。

Debug

从上面的知识中,我们知道组合函数是多个函数的组合,当组合函数返回的结果与预期不符合时,如何去调试它?

  • 对中间的值进行打印,并且知道当前执行位置
var log = MyCurrying((t, v) => {
  console.log(t, v);
  return v;
});
  • 在组合函数中,按照从左往右的顺序,给个函数套上log函数,就可以知道每次输出的值
var newFn = MyCompose(double,log('double--'),square,log('double--'));
var res2 = newFn(10);
// double-- 20
// double-- 400
// 400

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanekhi
系列文章
更多 icon
同类精品
更多 icon
继续加载