• 函数柯里化


    1.什么是柯里化

    柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。(百度百科搜一下就有)。

    从一个普通函数得到一个柯里化函数的过程叫做函数的柯里化,返回的函数称为经过柯里化的函数

    函数柯里化的技术来自于一种编程思想,就是一个复杂的问题可以通过分步的方式来求解,分步可以保证代码逻辑的清晰易懂。

    2.举个例子

    function add_1(a,b,c){//普通函数
        return a+b+c
    }
    console.log(add_1(1,2,3))
    
    function add_2(a,b){//柯里化函数
        return function(c){
            return a+b+c
        }
    }
    console.log(add_2(1,2)(3))
    
    function add_3(a){//柯里化函数
        return function(b){
            return function(c){
                return a+b+c
            }
        }
    }
    console.log(add_3(1)(2)(3))
    
    function curry(func){//函数的柯里化过程
        return function(a,b){
            return function(c){
                return func(a,b,c)
            }
        }
    }
    
    function curry2(func){//函数的柯里化过程
        return function(a){
            return function(b){
                return function(c){
                    return func(a,b,c)
                }
            }
        }
    }
    
    var add_2=curry(add_1)
    var add_3=curry2(add_1)
    

      我们可以通过分步的return来实现参数的分步传递,将add_1这个普通函数变为add_2或者add_3的过程称为函数的柯里化。可以预见随着传参的不断增加,柯里化过程就要不断的增加,是否可以从curry1,curry2这两个柯里化过程中得出一个通用的函数呢?这就是柯里化函数的通用式。

    柯里化函数的运行过程其实是一个参数的收集过程,我们将每一次传入的参数收集起来,最后传给函数执行。
    function add_n(func,args){//func是表示处理函数;args表示所有参数
        let length=func.length;//函数的形参个数,决定了要柯里化的次数
        var args=args || [];//柯里化时依次收集的参数存储变量,包含了所有已收集的传参
    
        return function(){
            let _args=Array.from(arguments);//收集柯里化时函数参数
            [].push.apply(_args,args);//将本轮柯里化运行时的参数添加到已收集的参数数组
    
            if(_args.length<length){//如果参数未收集完,即已收集的参数个数小于函数的形参个数时,递归调用
                return add_n.call(this,func,_args);
            }
    
            //当全部参数收集完成时,将所有参数传入函数中执行
            return func.apply(this,_args)
        }
    }
    
    
    var test=function(a,b,c){
        return a+b+c
    }
    
    var test_curry1=add_n(test)
    var test_curry2=add_n(test,[1])
    test_curry1(1)(2)(3) //6
    test_curry2(2)(3)   //6
    

      

    3.实际的应用场景

    理解了柯里化的过程,就要注意柯里化的思想更为重要,可以用来拆分逻辑。一个关于校验的例子:

    function check(partner,str){
        return partner.test(str)
    }
    
    function check_curry(partner){
        return function(str){
            return partner.test(str)
        }
    }
    
    var check_phone=check_curry(/^1[34578]d{9}$/)
    var check_email=check_curry(/^(w)+(.w+)*@(w)+((.w+)+)$/)
    
    //使用时较为复杂难用
    check(/^1[34578]d{9}$/,'18057192235')
    check(/^(w)+(.w+)*@(w)+((.w+)+)$/,'123456@qq.com')
    
    //使用时更为清晰明了
    check_phone('18057192235')
    check_email('123456@qq.com')
    

      在柯里化的实现中,我们知道柯里化虽然具有了更多的自由度,但同时柯里化通用式里调用了arguments对象,使用了递归与闭包,因此柯里化的自由度是以牺牲了一定的性能为代价换来的。只有在情况变得复杂时,才是柯里化大显身手的时候。

    参考文章:https://www.jianshu.com/p/5e1899fe7d6b

      

  • 相关阅读:
    静态页转换平台(StaticPol)-静态页生成终极解决方案
    用DataSetSurrogate加速WebService
    压缩和解压缩数据流
    Stream 和 byte[] 之间的转换(转)
    优化网站性能 提高网站速度访问速度的14条实践(转)
    常用WebServices返回数据的4种方法比较
    .Net 中的序列化与反序列化
    对象序列化反序列化
    ASP.Net中自定义Http处理及应用之HttpModule篇
    利用UrlRewrite,asp.net动态生成htm页面
  • 原文地址:https://www.cnblogs.com/scdisplay/p/10529411.html
Copyright © 2020-2023  润新知