函数式编程

2020-10-19  本文已影响0人  Dear丶BQ

为什么学习函数式编程

函数相关复习

函数是一等公民


把函数赋值给变量

//把函数赋值给变量
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]
  }
}

柯里化

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 }

总结

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函子

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函子

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=>{}
})

上一篇下一篇

猜你喜欢

热点阅读