美文网首页
函数式编程

函数式编程

作者: Dear丶BQ | 来源:发表于2020-10-19 17:31 被阅读0次

为什么学习函数式编程

  • 函数式编程随着react的流行受到越来越多的关注
  • vue3也开始拥抱函数式编程
  • 函数式编程可以抛弃this
  • 打包过程中可以更好的利用tree shaking过滤无用代码
  • 方便测试,方便并行处理
    很多库可以帮助我们进行函数式开发:lodash,underscore,remda

函数相关复习

函数是一等公民


把函数赋值给变量

//把函数赋值给变量
let fn=function(){
  console.log("hello")
}
fn()

//一个事例
const blogController={
  index(props){return views.index(props)},
  show(props){return views.show(props)},
  create(props){return views.create(props)},
  update(props){return views.update(props)},
  destroy(props){return views.destroy(props)},
 }
//优化
const blogController={
  index:views.index,
  show:views.show,
  create:views.create,
  update:views.update,
  destroy :views.destroy
 }

高阶函数


高阶函数-函数作为参数

function forEach(array ,fn){
 for(let i=0;i<array.length;i++){
    fn(array[i])
 }
}
let arr=[1,2,3,5]
forEach(arr,(item)=>{
  console.log(item)
})

function filter(array,fn){
  let results=[]
  for(let i=0;i<array.length;i++){
    if(fn(arrat[i])){
      results.push(array[i])
    }
 }
}
let arr=[1,2,3,5]
let res = filter(arr,()=>{
  return item % 2 === 0
})

高阶函数-函数作为返回值

function makeFn(){
  let msg='hello'
  return function(){
    console.log(msg)
  }
}
makeFn()() //"hello"

function once(fn){
  let done = false
  return function(){
    if(!done){
      done=true
       fn.apply(this,arguments)
    }
  }
}
let pay=once(function (money){
  console.log(`支付:${money}rmb`)
})

//模拟常用高阶函数map,every,some
const map=(array,fn)=>{
  let results=[]
  for(let value of array){
    results.push(fn(value))
 }
  return results
}

const every=(array,fn)=>{
  let result=true
  for(let value of array){
    result=fn(value)
    if(!result) break
 }
  return result
}

const some=(array,fn)=>{
  let result=false
  for(let value of array){
    result=fn(value)
    if(result) break
 }
  return result
}

let arr=[1,5,6,8]
arr=map(arr,v=>v*v)
let res=every(arr,v=>v>10)
let r=some(arr,v=>v % 2 === 0)

闭包


可以在另一个作用域中调用一个函数内部函数并访问到该函数的作用域中的成员

function makeFn(){
  let mes="hello"
  return function(){
    console.log(msg)
  }
}
const fn=makeFn() 
fn()

闭包的本质:函数在执行的时候会放到执行栈上当函数执行完毕后会从执行栈上移除,但堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员。

函数式编程基础

纯函数

纯函数必须有参数和返回值,并且相同的输入始终会得到相同的输出,而且没有任何可观察的副作用

let arr=[1,2,3,4,5]
//多次调用
arr.slice(0,3)//输出相同,纯函数
arr.splice(0,3)//输出不同,不纯


  • 函数式编程不会保留计算中间的结果,所以变量是不可变的
  • 我们可以吧一个函数的执行结果交给另一个函数去处理

lodash纯函数的代表

const _=require('lodash')
const array=['jack','bob','tim','lucy']

纯函数的好处
  • 可缓存,提高函数性能
const _=require('lodash')

function getArea(r){
  return MathPI*r*r
}

//模拟memoize
function memoize(fn)
  let cache={}
  return function(){
    let key = JOSN.stringify(arguments)
    cache[key]=cache[key]||f.apply(f,arguments)
    return cache[key]
  }
}
  • 可测试

  • 并行处理
    1.多线程环境下操作共享内存数据很可能出现意外情况
    2.纯函数不需要访问共享的内存数据,所以在并行环境可一任意运行纯函数

柯里化

function checkAge(min){
  return function (age){
    return age>=min
  }
}
let checkAge=min=>(age=>age>=min)
let check18=checkAge(18)
let check20=checkAge(20)
console.log(check18(24))

function curry(fun){
  return function curriedFn(...args){
    if(args.length<func.length){
      return function(){
        return curriedFn(...args.concant(Array.from(arguments)))
      }
    }
  }
}
  • 当一个函数有多个参数的时候先传递一部分参数调用他
  • 然后返回一个新的函数接收剩余的参数,返回结果

柯里化总结

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

函数组合

  • 概念:如果一个函数要经过多个函数处理才能得到最终的结果,这时候可以吧中间过程的函数合并成一个函数
  • 函数组合默认是从右到左执行
function compose(){}

lodash中FP模块-函数式编程柯里化后的模块
如果有多个参数时,函数优先数据之后原则

函子

函子Functor

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

class Container{
  static of(value){
    return new Container(value)
  }
  constructor(value){
    this._value=value
  }
  
  map(fn){
    return Container.of(fn(this._value)
  }
}
let r=Container.of(5).map(x=>x+1).map(x=>x*x)
console.log(r)//Container { _value: 36 }

总结

  • 函数是编程运算不直接操作值,而是由函子完成
  • 函子就是实现了map契约的对象
  • 我们可以把函子想象成盒子,盒子里面封装了一个值
  • 想要处理盒子重的值,我们需要给盒子的map方法专递一个处理值的函数(纯函数),由这个函数对值进行处理
  • 最终map方法返回一个包含新值的盒子(函子)

MayBe函子

class MayBe{
  static of(value){
    return new MayBe(value)
  }
  constructor(value){
    this._value=value
  }
  
  map(fn){
    return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value)
  }

  isNothing(){
    return this._value === null || this._value === undifined
  }
}

Either函子

  • Either两者中的任何一个,类似于if...else...的处理
  • 异常会让函数变得不纯,Either函子可以用来做异常处理
class Left{
  static of(value){
    return new Left(value)
  }
  constructor(value){
    this._value=value
  }
  
  map(fn){
    return this
  }
}

class Right{
  static of(value){
    return new Right(value)
  }
  constructor(value){
    this._value=value
  }
  
  map(fn){
    return Right.of(fn(this._value)
  }
}

function parseJSON(str){
   try{
    return Right.of(JSON.parse(str))
   }catch(e){
    return Left.of({error:e.message})
   }
}

IO函子

  • IO函子中的_value是一个函数,这里是把函数作为值来处理
  • IO函子可以把不纯的动作存储到_value中,延迟执行这个不纯的操作
  • 把不纯的操作交给调用者来处理
const  fp= require('lodash/fp')
class IO{
  static of(value){
    return new IO(function(){
      return value
    })
  }
  constructor(fn){
    this._value=fn
  }
  
  map(fn){
    return new IO(fp.flowRight(fn.this._value))
  }
}
let r =IO.of(process).map(p=>p.execPath)
console.log(r._value())

Task函子

const fs =require('fs')
const {task} =require('folktale/cocurrency.task')
const {spilt,find}=require('lodash/fp')

function readFile(filename){
  fs.readFile(filename,"utf-8",(err,data)=>{
    if(err) resolver.reject(err)
    resolver.resolve(data)
  })
}
readFile('pakage.json')
.map(split(''/n'))
.map(find(x=>x.inclues('version')))
.run()
.listen({
  onRejected:err=>{},
  onResolved:value=>{}
})

相关文章

  • RxSwift初探(1)

    一、前提:函数响应式编程思想 简单来说 函数响应式编程 = 函数式编程 + 响应式编程 (1)函数式 函数式编程是...

  • iOS 函数编程 & 链式编程

    函数式(链式)编程 函数式编程概念 函数式编程是种编程范式 函数式编程 Functional Programmin...

  • 函数式编程(一)—— 前置知识

    为什么要学函数式编程? 什么是函数式编程?函数式编程和面向对象编程的不同对于函数式编程思维方式的理解: 函数式编程...

  • 二十二、函数式编程、面向协议式编程

    函数式编程(Functional Prigramming) 函数式编程 函数式编程(Functional Prig...

  • Python中的函数式编程

    函数式编程 说到函数式编程,我们的重点在于为什么要采用函数式编程,而不是什么是函数式编程。 函数式编程的优点:一、...

  • RxSwift-初探

    函数响应式编程 一:函数式 函数式编程简称FP(Functional Programming),函数式编程就是一种...

  • 《Kotlin入门实战》CH5 | 函数与函数式编程

    函数与函数式编程 函数式编程与命令式编程最大的不同是:函数式编程的焦点在于数据的映射,命令式编程(imperati...

  • 函数响应式编程思想 & RxSwift 核心逻辑(一)

    函数响应式编程思想 函数响应式编程思想即是将函数式编程和响应式编程相结合。 函数式编程 顾名思义,就是像函数一样的...

  • RxJava系列|RxJava简介(一)

    函数响应式编程 函数式编程是一种编程范式。 常见的编程范式有:命令式编程、函数式编程和逻辑式编程。 面向对象就是一...

  • 了解C# 函数式编程

    什么是函数式编程 函数式编程是一种编程范式,维基百科对函数式编程定义如下: 函数式编程(英语:functional...

网友评论

      本文标题:函数式编程

      本文链接:https://www.haomeiwen.com/subject/runkmktx.html