函数式编程(纯函数、柯里化、函数组合、函子、接口幂等性)

目录​​​​​​​

纯函数

可缓存

loadsh中memoize缓存函数简单实现

副作用

示例 

接口的幂等性

函数的柯里化

lodsh中的curry方法简单实现

lodash中的fp模块

函数的组合

lodash中的flowRight方法简单实现

函子Functor 

IO函子

其它函子详细介绍


纯函数

对于相同的输入函数,始终得到相同的输出。

可缓存

因为存函数对相同的输入始终有相同的输出,所以可以把纯函数的的结果缓存起来。

loadsh中memoize缓存函数简单实现

function memoize(f){
    let cache = {}
    return function () {
        let arg_str = JSON.stringify(arguments);
        cache[arg_str] = cache[arg_str] || f.apply(f, arguments);
        return cache[arg_str];
    }
}
function getSum(a, b){
    console.log('执行了')
    return a + b;
}
const cacheSum = memoize(getSum);
cacheSum(1,2);
cacheSum(1,2);

副作用

如果函数依赖外部的状态就无法保证输出相同,就会带来副作用(让一个函数变为不纯)。

示例 

例如下面当mini改变时就会给checkAge带来副作用(相同的输入,输出不同)。 

let mini = 18;
function checkAge(age) {
 return age >= mini
}

副作用一般来源于:

  • 配置文件
  • 数据库
  • 获取用户的输入
  • ... 

接口的幂等性

接口可重复调用,在调用方多次调用的情况下,接口最终得到的结果是一致的。

函数的柯里化

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

function checkAge(min, age) {
    return age >= min;
}
// 柯里化后
function checkAge(min) {
    return function(age) {
        return age >= min;
    }
}

lodsh中的curry方法简单实现

function curry(func) {
    return function curriedFn(...args) {
        if(args.length < func.length) {
            return function() {
                // 注意arguments参数是类数组需要通过Array.from转化为数组
                return curriedFn(...args.concat(Array.from(arguments)))
            }
        }
        return func(...args)
    }
}
function getSum(a, b, c){
    return a + b + c;
}
const curried = curry(getSum);
curried(1, 2, 3);
const sumBC = curried(1)
sumBC(2, 3);

lodash中的fp模块

其中map、split等函数都用了函数柯里化。当只传入一个参数时,返回的是一个函数。

const fP = require('lodash/fp');
fp.map(fp.toUpper,['a', 'b', 'c']);
const toUpper = fp.map(fp.toUpper);
toUpper(['a', 'b', 'c']);
fp.split(' ', 'hello world');
const split = fp.split(' ');
split('hello world');

函数的组合

如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数和并成一个函数(g(f(x)) => h(g,f))。

lodash中的flowRight方法简单实现

function flowRight(...args) {
    return function(value) {
        return args.reverse().reduce(function(acc, fn) {
            return fn(acc)
        }, value)
    }
}
const reverse = arr => arr.reverse()
const first = arr => arr[0]
const f = flowRight(first, reverse)
f([1, 2, 3])

数组reduce方法介绍

JavaScript中常用函数方法(数组篇)_YF-SOD的博客-CSDN博客_javascript数组函数

 

函子Functor 

一个特殊的容器,通过一个普通的对象来实现,该对象具有map方法,map方法可以运行一个函数对值进行处理(变形关系)。

容器:包含值和值的变形关系,这个变形关系就是函数。

class Container {
  static of (value) {
    return new Container(value)
  }
  constructor (value) {
    this._value = value
  }
  map (fn) {
    return this._value ? Container.of(fun(this._value)) : Container.of(null)
  }
}
let r = Container.of(4).map(x => x * x) 

IO函子

IO函子中的_value是一个函数,这里把函数作为值来处理。

IO函子可以把不纯的动作存储在_value中,延迟执行这个不纯的操作,把不操作交给调用者处理。

const fp = require('lodash/fp')
class IO {
  static of (x) {
    return new IO(function () {
      return x;
    })
  }
  constructor (fn) {
    this._value = fn
  }
  map(fn) {
    return new IO(fp.flowRight(fn, this._value))
  }
}
let r = IO.of(process).map(p => p.execPath)
r._value()// 返回该文件路径

其它函子详细介绍

函子(Functor、Pointed、Maybe、Either、Mona式d、IO、Ap) - 知乎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值