乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      ES6之函數(shù)擴(kuò)展

       quasiceo 2018-09-30

      目錄
      一、 函數(shù)參數(shù)的默認(rèn)值
      二、rest參數(shù)
      三、嚴(yán)格模式
      四、name 屬性
      五、箭頭函數(shù)
      六、雙冒號運算符(目前報錯,只是提案。)
      七、重點: 尾調(diào)用優(yōu)化,尾遞歸優(yōu)化( Fibonacci 數(shù)列)
      八、函數(shù)參數(shù)尾逗號

      尾遞歸
      總結(jié)一下,遞歸本質(zhì)上是一種循環(huán)操作。純粹的函數(shù)式編程語言沒有循環(huán)操作命令,所有的循環(huán)都用遞歸實現(xiàn),這就是為什么尾遞歸對這些語言極其重要。對于其他支持“尾調(diào)用優(yōu)化”的語言(比如 Lua,ES6),只需要知道循環(huán)可以用遞歸代替,而一旦使用遞歸,就最好使用尾遞歸。

      下面是一個正常的遞歸函數(shù)。

      function sum(x, y) {
        if (y > 0) {
          return sum(x + 1, y - 1);
        } else {
          return x;
        }
      }
      
      sum(1, 100000)
      // Uncaught RangeError: Maximum call stack size exceeded(…)
      

      上面代碼中,sum是一個遞歸函數(shù),參數(shù)x是需要累加的值,參數(shù)y控制遞歸次數(shù)。一旦指定sum遞歸 100000 次,就會報錯,提示超出調(diào)用棧的最大次數(shù)。

      蹦床函數(shù)(trampoline)可以將遞歸執(zhí)行轉(zhuǎn)為循環(huán)執(zhí)行。

      function trampoline(f) {
        while (f && f instanceof Function) {
          f = f();
        }
        return f;
      }
      

      上面就是蹦床函數(shù)的一個實現(xiàn),它接受一個函數(shù)f作為參數(shù)。只要f執(zhí)行后返回一個函數(shù),就繼續(xù)執(zhí)行。注意,這里是返回一個函數(shù),然后執(zhí)行該函數(shù),而不是函數(shù)里面調(diào)用函數(shù),這樣就避免了遞歸執(zhí)行,從而就消除了調(diào)用棧過大的問題。

      然后,要做的就是將原來的遞歸函數(shù),改寫為每一步返回另一個函數(shù)。

      function sum(x, y) {
        if (y > 0) {
          return sum.bind(null, x + 1, y - 1);
        } else {
          return x;
        }
      }
      

      上面代碼中,sum函數(shù)的每次執(zhí)行,都會返回自身的另一個版本。

      現(xiàn)在,使用蹦床函數(shù)執(zhí)行sum,就不會發(fā)生調(diào)用棧溢出。

      trampoline(sum(1, 100000))
      // 100001
      

      蹦床函數(shù)并不是真正的尾遞歸優(yōu)化,下面的實現(xiàn)才是。

      function tco(f) {
        var value;
        var active = false;
        var accumulated = [];
      
        return function accumulator() {
          accumulated.push(arguments);
          if (!active) {
            active = true;
            while (accumulated.length) {
              value = f.apply(this, accumulated.shift());
            }
            active = false;
            return value;
          }
        };
      }
      
      var sum = tco(function(x, y) {
        if (y > 0) {
          return sum(x + 1, y - 1)
        }
        else {
          return x
        }
      });
      
      sum(1, 100000)
      // 100001
      

      上面代碼中,tco函數(shù)是尾遞歸優(yōu)化的實現(xiàn),它的奧妙就在于狀態(tài)變量active。默認(rèn)情況下,這個變量是不激活的。一旦進(jìn)入尾遞歸優(yōu)化的過程,這個變量就激活了。然后,每一輪遞歸sum返回的都是undefined,所以就避免了遞歸執(zhí)行;而accumulated數(shù)組存放每一輪sum執(zhí)行的參數(shù),總是有值的,這就保證了accumulator函數(shù)內(nèi)部的while循環(huán)總是會執(zhí)行。這樣就很巧妙地將“遞歸”改成了“循環(huán)”,而后一輪的參數(shù)會取代前一輪的參數(shù),保證了調(diào)用棧只有一層。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多