最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • javascript函数式编程

    正文概述 掘金(echo_dc)   2021-01-31   509

    函数式编程:用来描述数据之间的映射

    思维方式:实现世界的事物与事物之间的联系抽象到函数世界,通过封装、多态和继承来演示事物的联系

    理解起来太费脑,有几个例子看一下函数式编程的特点及优势

    首先常见的有函数作为参数,函数作为返回值,函数可以存储在变量中(即JS世界中函数一等公民)

    1.函数作为参数

    // forEach
    function forEach (array, fn) {
        for(let i=0;i<array.length;i++){
            fn(array[i])
        }
    }
    

    2.函数作为返回值

    // once  jq中的once只执行一次
    function once (fn) {
        let done = false
        return function () {
            if (!done) {
            done = true
            return fn.apply(this, arguments)
        }
    }
    

    上述方法的使用,抽象出了我门需要的功能而不是每当我们遇到一个问题就写一遍函数实现,这也做的主要意义抽象了细节,只需要我们关注目标,这种函数中调用函数的方式也称作高阶函数。

    这里再介绍另外一个概念:闭包

    本质:函数在执行的时候会放在一个执行栈上(关于函数的执行,我会在另外一篇文章里详细写道)当函数执行完毕之后会从执行栈上移除,但是堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员。

    下面来看一个闭包的使用案例

    // 生成计算数字的多少次幂的函数
    function makePower (power) {
        return function (x) {
            return Math.pow(x, power)
        }
    }
    let power2 = makePower(2)
    let power3 = makePower(3)
    
    console.log(power2(4))
    

    上面这个例子是使用闭包的一个很好的封装。

    第三介绍会介绍一下纯函数

    纯函数:相同的输入永远会输出相同的输出,而且没有任何可观察的副作用

    纯函数可以理解为数学中的函数y=f(x)

    用例子展示 :数组的slice(纯函数)和splice(不是纯函数)

    slice返回数组中的指定部分,不会改变原数组

    splice对数组进行操作返回该数组,会改变原数组

    使用纯函数的好处:

    1.可以缓存:

    以下是纯函数缓存的实现

    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]
        }
    }
    

    可测试:纯函数让测试更方便

    并行处理:在多线程环境下操作共存的内存数据

    第四函数柯里化

    使用柯里化解决硬编码的问题

    eg:函数内部硬编码
    function checkAge (age) {
        let min = 18
        return age >= min
    }
    
    //普通纯函数方法
    function checkAge (min, age) {
        return age >= min
    }
    
    checkAge(18, 24)
    checkAge(18, 20)
    checkAge(20, 30)
    
    // 柯里化
    function checkAge (min) {
        return function (age) {
            return age >= min
        }
    }
    
    //ES6写法
    let chechAge=min=>(age=>age=>min)
    let checkAge18 = checkAge(18)
    let checkAge20 = checkAge(20)
    checkAge18(24)
    checkAge18(20)
    

    柯里化:当一个函数有多个参数的时候先传第一部分参数调用它,然后返回一个新的函数接受剩余的参数,返回结果。

    lodash中的柯里化案例

    const _ = require('lodash')
    const match = _.curry(function (reg, str) {
        return str.match(reg)
    })
    const haveSpace = match(/\s+/g)
    const haveNumber = match(/\d+/g)
    console.log(haveSpace('hello world'))
    console.log(haveNumber('25$'))
    const filter = _.curry(function (func, array) {
        return array.filter(func)
    })
    console.log(filter(haveSpace, ['John Connor', 'John_Donne']))
    const findSpace = filter(haveSpace)
    console.log(findSpace(['John Connor', 'John_Donne']))
    

    模拟实现

    function curry (func) {
        return function curriedFn (...args) {
        // 判断实参和形参的个数
        if (args.length < func.length) {
            return function () {
            return curriedFn(...args.concat(Array.from(arguments)))
            }
        }
        // 实参和形参个数相同,调用 func,返回结果
        return func(...args)
        }
    }
    

    总结:

    1.柯里化可以让我们给一个函数传第较少的参数得到一个已经记住了某些固定参数的新函数

    2.这是一种函数参数的‘缓存’

    3.让函数变的更加灵活,让函数的粒度更小

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

    第四介 函数组合

    函数柯里化如果遇到多个函数嵌套的时候如果其中一个函数在执行中出错,我们是很难发现问题的,这就需要将里面的函数拆开组合起来。就有了函数组合的概念。

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

    我们以lodash的flowRIght方法为例子(输入的函数从右到左执行)

    模拟实现:

    // 多函数组合
    function compose (...fns) {
        return function (value) {
            return fns.reverse().reduce(function (acc, fn) {
                return fn(acc)
              }, value)
         }
    }
    // ES6
    const compose = (...fns) => value => fns.reverse().reduce((acc, fn) =>
    fn(acc), value)
    
    
    const toUpper = s => s.toUpperCase()
    const reverse = arr => arr.reverse()
    const first = arr => arr[0]
    const f = compose(toUpper, first, reverse)console.log(f(['one', 'two', 'three']))
    

    第五 函子

    1.Functor (函子)

    正对函数式编程中我们需要把副作用控制在可控的范围内,异常处理,异步操作等因此有就有了函子

    Functor

    容器:包含值和值的变形关系(函数)

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

    // 一个容器,包裹一个值
    class Container {
        // of 静态方法,可以省略 new 关键字创建对象
        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)
    

    函子的特点:

    1.函数式编程的运算不直接操作值,而是由函子完成 

    2.函子就是一个实现了 map 契约的对象 

    3.我们可以把函子想象成一个盒子,这个盒子里封装了一个值 

    4.想要处理盒子中的值,我们需要给盒子的 map 方法传递一个处理值的函数(纯函数),由这 个函数来对值进行处理 

    5.最终 map 方法返回一个包含新值的盒子(函子)


    下载网 » javascript函数式编程

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元