第一章 javaScript 深度解析 模块一

104 阅读5分钟

函数式编程与 JS 异步编程 手写 promise

一 函数式编程范式

1. 函数式编程概念

2. 函数式是一等公民

3. 高阶函数 - 函数作为参数

forEach filter 函数都是通过函数作为参数,来二次封装 for 循环

4. 高阶函数 - 函数作为返回值 Once apply

使用高阶函数的意义 抽象可以帮助我们屏蔽细节,只需要关注我们的目标 高阶函数是用来抽象通用的问题

5.常用高阶函数

map 函数 : 返回一个新的数组,数组中的元素为原始数组调用函数处理后的值 arr.map((currentValue, index, arr)=>{},thisIndex) every:用来检测数组中每一个参数是否符合某个条件 some: 用来检测数组中是否至少有一个符合某个条件

6.匿名函数 (闭包)

作用: 延长了内部函数变量的作用范围 闭包的本质:函数在执行的时候会被放在一个执行栈上, 当函数执行完成, 函数会进行释放从执行栈上移除,但是堆上的作用域成员因为被外部引用不能被释放,因此内部函数依然可以访问外部函数的成员

7.纯函数

概念:相同的输入永远得到相同的结果

纯函数就类似于数学中的函数(用来描述输入和输出的关系) y=f(x)

slice:数组中截取指定位置的函数,返回新函数, 原数组不变

splice: 数组中截取指定位置的函数, 返回原函数,新函数不变 好处: 可缓存:因为每次返回结果都一样, 说明可缓存。 可测试

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

loadsh 中的函数柯里化: _curry(func)

  • 功能:创建一个函数,该函数接收一个或多个 func 的参数,如果 func 所需要的参数都被提供则执行 func 函数并返回执行的结果, 否则继续返回该函数并等待接收剩余的参数 柯里化函数可以把多元函数转换为一元函数

  • 示例

function getNum(a,b,c){
    return a+b+c
}
const curried = _curry(getNum)
console.log(curried(1,2,3))    // 6
console.log(curried(1)(2,3))   // 6
console.log(curried(1,2)(3))   // 6

函数柯里化案例

    cosnt _ = require("lodash")
    
    const match  = _.curry((reg,str)=> str.match)
    // 匹配一个字符串中是否有空格
    const haveSpace = match(/\s+/g)
    // 匹配一个字符串中是否有数字
    const haveSpace = match(/\d+/g)
    console.log(haveSpace('helloword'))
    console.log(haveSpace('hell2oword'))
    

柯里化原理模拟 ???

柯里化总结

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

函数组合(compose): 如果一个函数要经过多个函数处理才能得到最终值, 这个时候可以把中间过程的函数合并成一个函数

  • 函数就像是数据的管道,函数组合就是把这些管道连接起来, 让数据穿过多个管道形成最终结果
  • 函数组合默认是从右到左执行

lodash中的函数组合:可以接收多个参数, 上面compose 只可以接收两个参数

  • flowRight(a,b,c) -flowLeft(a,b,c)

组合函数的原理模拟

  • reduce 方法对数组中的每个元素执行一个由您提供的 reducer函数(升序执行),将其结果汇总为单个返回值
  • 满足结合律

point Free:概念性。

函子(functor)

  • 为什么要学习函子:到目前为止已经学习了函数式编程的一些基础,但是外面还没有演示在函数式编程中如何把副作用控制在可控制范围内,异常处理, 异步操作等

  • 什么是functor:

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

函子总结

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

maybe 函子

  • 可以处理传入的值为null 的情况

either 函子

  • either 函子, 只两者中的任意一个,类似于 if... else ... 的处理
  • 异常会让函数变的不纯, Either 函子可以用来做异常处理 try {} catch(e){} 用法

IO 函数

  • IO 函子中的 _value 是一个函数,这里把函数作为值来处理。
  • IO 函子可以把不纯的动作存储到 _value 中, 延迟执行这个不纯的操作(惰性执行),包装当前的操作纯
  • 把不不纯的操作交给调用者来处理