mandywang

函数式编程

导语:

  • 为什么要学习函数编程以及什么是函数式编程

  • 函数式编程的特性(纯函数,柯里化,函数组合等)

  • 函数式编程的应用场景

  • 函数式编程库Lodash

为什么要学习函数式编程

  • 函数式编程随着React的流行受到越来越多的关注

  • vue3也开始拥抱函数式编程

  • 函数式编程可以抛弃this

  • 打包过程中可以更好的利用tree shaking过滤无用代码

  • 方便测试和并行处理

  • 多库协助开发:Lodash,underscore,ramda

什么是函数式编程

函数式编程(Functional Programming FP),是编程的一种范式。

而函数式编程中的函数不是指程序中的函数方法,而是把数学中的函数映射关系运用到了程序中。

  • 高阶函数:可以把函数作为参数传递给另一个函数,也可以把函数作为另一个函数的返回结果

// forEach
function forEach(array,fn) {
    for (let i=0; i<array.length;i++){
        fn(array[i])
    }
}
// filter
function filter (array, fn) {
    let results = []
    for (let i=0;i<array.length;i++){
        if (fn(array[i])){
            results.push(array[i])
        }
    }
    return results
}
// 函数作为返回值
function hello () {
    let msg = \'hello Function\'
    return function () {
        console.log(msg)
    }
}
const fn = hello()
fn()
​
function once(fn) {
    let done = false
    return function () {
        if (!done) {
            done = true
            return fn.apply(this,arguments)
        }
    }
}
let pay = once(function(money){
    console.log(`支付:${money}RBM`)
})
pay(5)
pay(5)
pay(5)
pay(5)
// 只会支付一次
支付了:5 RMB
​
// 面向过程的方式
let array = [1,2,3,4]
for (let i = 0; i<array.length;i++){
    console.log(array[i])
}
// 高阶函数
forEach(array,item => {
    console.log(item)
})
let r = filter(array,item => {
    return item % 2 === 0
})
使用高阶函数的意义:抽象可以帮我们摒弃细节,只关注目标,高阶函数式用来抽象通用的问题

常用的高阶函数:forEach,map,filter,every,some,find/findIndex,reduce,sort......

const map = (array,fn) => {
    let results = []
    for(const value of array) {
        results.push(fn(value))
    }
    return results
}
const every = (array,fn) => {
    let result = true
    for (const value of array){
        result = fn(value)
        if (!result) {
            break
        }
    }
    return result
}
​
const some = (array,fn) =>{
    let result = false
    for (const value of array){
        result = fn(value)
        if (result) {
            break
        }
    }
    return result
}

 

  • 闭包: 函数执行的时候会放到一个执行栈上,执行完就会从执行栈移除,但是堆上的作用域成员因为应用不能释放,因此内部函数依然可以访问外部函数的成员

// 第一个数是基本工资,第二个数是绩效工资
function makeSalary (x) {
    return function(y) {
        return x + y
    }
}
let salaryLevel1 = makeSalary(1500)
let salaryLevel2 = makeSalary(2500)

 

  • 纯函数:

    • 相同的输入永远会得到相同的输出,而且没有副作用(lodash是一个纯函数的功能库,提供了对数组,数字,对象,字符串,函数等操作的一些方法slice-纯函数,splice-不纯的函数)

    • 纯函数的好处:可缓存,可测试,没有副作用

  • 柯里化

    • 当一个函数用多个参数的时候,先传递一部分参数调用它,然后返回一个新的函数接收剩余的参数,返回结果

    • 可以降低函数的颗粒度

    • 对函数参数的‘缓存’

    • 可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能

  • 函数组合:纯函数和柯里化很容易出现洋葱代码

    • 函数就像数据的管道,函数组合就是把这些管道链接起来,让数据穿过多个管道形成最终结果

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

    // 一个容器包裹一个值
    class Container {
        static of (value) {
            return new Container(value)
        }
        constructor (value) {
            this._value = value
        }
    }
    ​
    // map 方法,传入变形关系,将容器里的每一个值映射到另一个容器
    map (fn) {
        return Container.of(fn(this._value))
    }
    ​
    // 测试
    Container.of(3).map(x => x + 2).map(x => x*x)

     

    总结:函数式编程的运算不直接操作值,而是由涵子完成,涵子就式一个实现了map契约的对象,函子就像一个盒子,这个盒子封装了一个值,想要处理盒子中的值我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数来对值进行处理,最终map方法返回一个包含新值的盒子(函子)

    MayBe函子的作用就是可以对外部的空值做处理(控制副作用在允许的范围)

    Either函子:类似于if...else... 的处理,可以用来处理异常处理

    IO函子:把函数作为值来处理

    Pointed函子:实现了of静态方法的函子,of 是未了避免使用new来创建对象,of方法用来把值放到上下文context

分类:

技术点:

相关文章:

  • 2021-05-20
  • 2019-10-11
  • 2022-03-03
  • 2021-04-09
  • 2022-12-23
  • 2021-09-30
  • 2021-09-30
  • 2021-07-16
猜你喜欢
  • 2021-09-30
  • 2021-12-10
  • 2022-12-23
  • 2021-12-31
  • 2021-11-06
  • 2022-02-11
  • 2021-11-06
相关资源
相似解决方案