1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
      <output id="hzk7v"></output>
    2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
    3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

      详解用场景去理解函数柯里化(入门篇)

       更新时间£º2019年04月11日 12:04:17   作者£ºRobinsonZhang   我要评论

      这篇文章主要介绍了用场景去理解函数柯里化(入门篇)£¬文中通过示例代码介绍的非常详细£¬对大家的学习或者工作具有一定的参考学习价值£¬需要的朋友们下面随着小编来一起学习学习吧

      前言

      函数柯里化就是将多参简化为单参数的一种技术方式£¬其最终支持的是方法的连续调用£¬每次返回新的函数£¬在最终符合条件或者使用完所有的传参时终止函数调用¡£

      场景实例

      与其他文章不同£¬我在本文会重点分享一些柯里化的经典使用场景£¬让你在学会这点技巧后能切实的提升代码的可维护性¡£

      编写可重用小模块代码

      比如我们有个方法部分逻辑前置是相同的£¬后面的执行是因为参数不同导致结果不同的£¬下面是代码部分¡£
      计算商品的折扣£¬我们需要根据不同的折扣以?#21543;?#21697;的入参返回其?#23548;?#30340;价格¡£

      // before
      function getPrice(price,discount){
      	return price * discount;
      }
      
      let price = getPrice(500,0.1);
      
      
      // after 
      function getPrice(discount){
      	return price =>{
       	return price * discount
       }
      }
      // 使用,在这?#36136;?#29992;效果下£¬我们可以固定的肢解拿到百分之十折扣的函数£¬
      //也就是针对使用0.1折扣的商品价格都可以简化这个折扣的传递,从而达到简化参数的目的
      //那么从函数的运行上来讲£¬也比之前的效率高了£¬如果解析折扣的过程比?#32454;?#26434;
      let tenDiscount = getPrice(0.1);
      let price = tenDiscount(500);
      
      let price = getPrice(0.1)(500)
      
      
      

      看上去有点鸡肋£¬因为我们本来的写法很简单£¬使用了柯里化反而让简单的事情变得复杂了£¬这主要是因为没有达到我们要把一个函数变成柯里化的经典场景¡£假如你下面的代码变成了下面这样£¬也许你就能觉察出如果有使用柯里化就会非常方便了£¬因为针对第一个参数做了若干的处理£¬甚至可以称为一个算法或者完整的逻辑判断流程£¬那么如果有多个参数调用都涉及这个方法的调用£¬同一个参数的这部分逻辑是相同可以共用跳过的¡£codepen连接£º链接

      // complexed fun 
      function getPriceComplex(price,discount){
       let actualDiscount = 1;
       if(discount > 0.8 ) {
       	actualDiscount = 0.8;
       } else if(discount > 0.5){
       	actualDiscount = 0.5;
       } else {
       actualDiscount = 0.1;
       }
       let actualPrice = price - price % 100 ;
      	return actualPrice * actualDiscount;
      }
      
      // complexed fun better
      function getPriceComplexBetter(discount){
       let actualDiscount = 1;
       if(discount > 0.8 ) {
       	actualDiscount = 0.8;
       } else if(discount > 0.5){
       	actualDiscount = 0.5;
       } else {
       actualDiscount = 0.1;
       }
       return price => {
       	 let actualPrice = price - price % 100 ;
      			return actualPrice * actualDiscount;
       }
      }
      
      
      console.log(getPriceComplex(500,0.9))
      let exp1 = getPriceComplexCp(0.9);
      console.log(exp1);
      /** price => {
       let actualPrice = price - price % 100;
       return actualPrice * actualDiscount;
      }*/
      // 相同的输入参数时 可以缓存下之前代码逻辑的执行结果 实现模块的可重用£¬如果你之前的逻辑是一个纯函数
      console.log(exp1(500))// 400
      console.log(exp1(400))// 320
      
      
      // get real discount 
      // 当你针对第一个参数的逻辑较为复杂时£¬出于可维护角度£¬建议如此 ;
      // 当你另外一个逻辑也是基于这个返回结果时£¬出于重用角度£¬建议如此
      function getActualDiscount(discount){
       let actualDiscount = 1;
       if(discount > 0.8 ) {
       	actualDiscount = 0.8;
       } else if(discount > 0.5){
       	actualDiscount = 0.5;
       } else {
       actualDiscount = 0.1;
       }
       return actualDiscount;
      }
      // complexed fun best
      function getPriceComplexBest(discount){
       let actualDiscount =getActualDiscount(discount);
       return price => {
       	 let actualPrice = price - price % 100 ;
      			return actualPrice * actualDiscount;
       }
      }
      

      总结£¬无论如何£¬我们使用某种技巧或者封装或者其他£¬都是为了让代码更可用£¬原先复?#30828;?#21487;测试¡¢不可理解的代码变得更有调理£¬更节省性能的角度出发的£¬当你的思维方式中有这种的时候£¬你就不会觉得是为了形式而使用£¬而是你的编码习惯或者风格就是如此¡£

      简单?#33041;?#26222;通函数为柯里

      假如我们需要把一个原来非柯里的函数如何快速?#33041;še?#22312;不影响原来主要代码逻辑的情况下£¬想下我们代码可能如何写£¿

      // 只考虑两个参数
      function add(a,b){
       return a + b
      }
      
      // 但如果你是用柯里化的方式:两个参数的时候 £¬但这样对原代码变动非常大£¬对于一些复杂的逻辑£¬这基本不可能
      function curryAdd(...args){
       return (...newArgs) => {
       	return anoNumber * number;
       };
      }
      
      // 我们写一个通用的柯里化函数的方式,经过这个函数的转换£¬我们可以将调用方式简化
      function curry = (fn,...args){
      	return (..._args)=>{
       	return fn(...args, ..._arg);
       }
      }
      
      let curryAdd = curry(add,10);
      let curryAdd2 = curryAdd(11)
      
      

      不定参数的累加

      一个比较经典的练手题£¬把下面的代码用柯里化的方式实现£¬其难点简单分析如下£º如果你没有了解过柯里化£¬可能觉得基本无法完成¡£

      1 动态入参个数£¬这个也许还可以通过arguments循环完成2 每次都能接受新的参数继续累加£¬这必须是返回新函数并带有之前的结果£¬要求是具有柯里化特点3 每次不在追加参数时£¬需要能得到的值£¬这个需要你了解toString方法来改变结果值

      实现一个add方法£¬使计算结果能够满足如下预期£º add(1)(2)(3) = 6

      add(1, 2, 3)(4) = 10

      add(1)(2)(3)(4)(5) = 15

      function add() {
       // 第一次执行时£¬定义一个数组专门用来存储所有的参数
       var _args = [].slice.call(arguments);
       // 在内?#21487;?#26126;一个函数£¬利用闭包的特性保存_args并收集所有的参数值,执行时已经收集所有参数为数组
       var adder = function () {
        var _adder = function() {
         // 执行收集动作£¬每次传入的参数都累加到原参数
         [].push.apply(_args, [].slice.call(arguments));
         return _adder;
        };
        // 利用隐式转换的特性£¬当最后执行时隐式转换£¬并计算最终的值返回
        _adder.toString = function () {
         return _args.reduce(function (a, b) {
          return a + b;
         });
        }
        return _adder;
       }
       return adder(_args);
      }
      

      备注£ºcodepen中的console.log方法被重写£¬会有报错的问题£¬你可以直接通过浏览器的console控制台调试这个方法¡£

      部分参数应用

      部分参数应用是指有些场景是希望固定传递多个参数£¬来得到其固定的函数£¬然后基于这个函数去执行代码¡£类似于第一个例子中的一个折扣参数得出折扣算法的使用¡£我们将第一个例子再复杂化一些¡£就会变成这样的¡£

      function getActualDiscount(custoemrLevel,discount){
      	
      }
      function getPriceComplex (custoemrLevel,discount){
      	let actualDiscount = getActualDiscount(custoemrLevel,discount);
       return price=>{
       	return price * actualDiscount;
       }
      }
      // 等级一的折扣策略 
      let strategyLev1WithOnepoint = getPriceComplex('lev1',0.1) ;
      let actualPrice = strategyLev1WithOnepoint(500);
      
      

      以上所述是小编给大家介绍的用场景去理解函数柯里化(入门篇)详解整合£¬希望对大家有所帮助£¬如果大家有任?#25105;?#38382;请给我留言£¬小编会及时回复大家的¡£在此也非常?#34892;?#22823;家对脚本之家网站的支持£¡

      相关文章

      最新评论

      3dÊÔ»úºÅÖвÊÍø

        1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
          <output id="hzk7v"></output>
        2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
        3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

            1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
              <output id="hzk7v"></output>
            2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
            3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>