美文网首页JavaScript 进阶营
javascript高阶函数应用——柯里化

javascript高阶函数应用——柯里化

作者: 成熟稳重的李先生 | 来源:发表于2019-08-10 12:22 被阅读4次

    高阶函数:
    在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:
    1.接受一个或多个函数作为输入:forEach sort map filter reduce
    2.输出一个函数:lodash.curry
    不过它也可以同时满足两个条件:Function.prototype.bind

    这里对高阶函数不过多讲解,这节我们来学习柯里化。

    在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术 。在直觉上,柯里化声称“如果你固定某些参数,你将得到接受余下参数的一个函数”。所以对于有两个变量的函数yx,如果固定了 y = 2,则得到有一个变量的函数 2x——柯里化·百度百科

    由以上,我们来一段代码

    // 假设我们要写一个+1的函数
    function sum(x, y){
        return x+y
    }
    //此时,这个sum就称为对于x和y的函数
    sum(1, 2)  // 3
    //由柯里化的概念,我们可以固定一个参数,使后续操作可以只传一个参数
    function addOne(y){
      return 1+y
    }
    addOne(2) //3
    addOne(7) //8
    
    //可如果,又有一个+2的需求呢,那好,我再写一遍
    function addTwo(a){
      return a+2
    }
    addTwo(3) //5
    
    //那再有+3,+4的需求呢? 
    

    这时,我们就可以使用柯里化来简便这个过程,柯里化是惰性求值的,即在你需要的到值的时候,再取值。
    这里借鉴一下《JavaScript设计模式与开发实践》书中的例子

    假设我们要编写一个计算每月开销的函数。在每天结束之前,我们都要记录今天花掉了多少钱。代码如下:

    var monthlyCost = 0; 
    var cost = function( money ){ 
     monthlyCost += money; 
    }; 
    cost( 100 ); // 第 1 天开销
    cost( 200 ); // 第 2 天开销
    cost( 300 ); // 第 3 天开销
    //cost( 700 ); // 第 30 天开销
    alert ( monthlyCost ); // 输出:600
    

    通过这段代码可以看到,每天结束后我们都会记录并计算到今天为止花掉的钱。但我们其实并不太关心每天花掉了多少钱,而只想知道到月底的时候会花掉多少钱。也就是说,实际上只需要在月底计算一次。如果在每个月的前 29 天,我们都只是保存好当天的开销,直到第 30 天才进行求值计算,这
    样就达到了我们的要求。

    以上需求,我们就可以利用柯里化的思想来惰性求值,先将一部分参数存起来,当我们实际需要值的时候再来求值,虽然下面的 cost 函数还不是一个 currying 函数的完整实现,但有助于 我们了解其思想。

    var cost = (function(){ 
        var args = []; 
        return function(){ 
            if ( arguments.length === 0 ){ 
                var money = 0; 
                for ( var i = 0, l = args.length; i < l; i++ ){ 
                    money += args[ i ];
                }
                return money;
            }else{
                 [].push.apply(args, arguments)
                //或者 args = args.concat([].slice.call(arguments))
            }
        }
    })()
    cost(100)
    cost(253)
    cost()  // 353
    

    接下来,我们要写一个正式的curry函数

    // 第一个参数是我们需要柯里化的原函数,同时,在它后边你还可以传入一些初始的值。
    //这里,你可以注明形参(只传fn的话),因为考虑到初始值的问题,我们就以arguments来代替了
    var currying = function( fn ){ // 参数为原函数
           var args = []; 
           return function(){   // 柯里化后的新函数
               if ( arguments.length === 0 ){  // 参数数数量为0时,意为求值
                   return fn.apply( this, args ); 
               }else{     // 否则,将这些值保存起来
                   [].push.apply( args, arguments ); 
                   return arguments.callee; 
               } 
           } 
    };
    var cost = (function(){ 
           var money = 0; 
           return function(){ 
               for ( var i = 0, l = arguments.length; i < l; i++ ){ 
                   money += arguments[ i ]; 
               } 
               return money; 
           } 
    })();
    var cost = currying( cost ); // 转化成 currying 函数
    cost( 100 ); // 未真正求值
    cost( 200 ); // 未真正求值
    cost( 300 ); // 未真正求值
    alert ( cost() ); // 求值并输出:600
    

    至此,我们就完成了对柯里化的初步了解

    相关文章

      网友评论

        本文标题:javascript高阶函数应用——柯里化

        本文链接:https://www.haomeiwen.com/subject/iifkjctx.html