js遞歸優化

遞歸優化

遞歸在咱們平時擼碼中會常常用到,不過可能不少人不知道遞歸的弊端,就是會致使調用棧愈來愈深。若是沒有節制的使用遞歸可能會致使調用棧溢出。
  • 那什麼是遞歸呢?
    遞歸調用是一種特殊的嵌套調用,是某個函數調用本身或者是調用其餘函數後再次調用本身的,只要函數之間互相調用能產生循環的則必定是遞歸調用,遞歸調用一種解決方案,一種是邏輯思想,將一個大工做分爲逐漸減少的小工做,好比說一個和尚要搬50塊石頭,他想,只要先搬走49塊,那剩下的一塊就能搬完了,而後考慮那49塊,只要先搬走48塊,那剩下的一塊就能搬完了,遞歸是一種思想,只不過在程序中,就是依靠函數嵌套這個特性來實現了。
  • 那什麼又是調用棧呢?
    下面的是我寫的一個簡單的遞歸調用,經過斷點咱們能夠看到每執行一個test函數,調用棧就會多一個test函數。
    當咱們執行到i=0的時候,這個時候調用棧是最深的有11個test函數,以後又會逐個移除test函數,能夠看圖二的動圖,能夠看出調用棧是先進後出的
function test (i) {
    if (i < 0) return
    test(--i)
}
// 這個會調用自身11次
test(10)

圖1:
遞歸優化-調用棧
圖2:
遞歸優化-圖2javascript

那怎麼對遞歸進行優化呢,既能起到遞歸的做用又不會加深調用棧

這裏會用到while循環的思想,調用棧之因此會加深主要是由於方法內調用方法,必須等待方法執行完成這個任務纔算是真正的結束,就像A同窗有個任務1,這個任務是讓B同窗完成任務2,在B同窗沒有完成以前,A同窗一直處理工做狀態。
那while循環是什麼原理呢,能夠理解爲將有調用關係的方法平鋪爲同一級別。這須要引入額外的方法來作調度,原本test方法須要調用本身10次的,如今用方法b經過標記的方法來決定是否須要調用test方法java

  • 下面的的例子就是實現遞歸優化的實現方法(這裏複製於阮一峯的es6教程)

  • 這是一個很巧妙的方法,我說下它的實現步驟:
  1. 利用閉包將f方法保留(這裏的f方法就是咱們須要遞歸調用的方法)
  2. 建立value、active、accumulated三個變量,並利用了閉包原理避免被垃圾回收
  3. accumulated是保存每次f方法調用後須要傳入f的新的形參,active是標記f方法是否執行到了最後一次循環,value是記錄須要返回的值
  4. 下面的由於tco會return一個新的函數accumulator,因此sum=accumulator,而後再accumulator內只要accumulated長度不爲0,while就會一直執行,每次執行sum方法就會accumulated.push(arguments)方法,這樣accumulated長度就不會爲0。因此只要f.apply(this, accumulated.shift())執行的時候一旦不調用sum(x + 1, y - 1)方法,accumulated就不會有push操做,這時while就會中止。而後就是active,咱們看到if (!active) {...}這個操做,這裏保證了只有第一次調用accumulator方法時會進入while循環,剩下的只是起到accumulated.push(arguments)的做用。直到while循環中止,return出來的就是通過n次調用f方法後返回的值了。

  • 這樣就能夠把一個遞歸調用轉換爲while循環實現了
function tco(f) {
  var value;
  var active = false;
  var accumulated = [];

  return function accumulator() {
  // 這裏accumulated將形參入棧
    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)
這裏可能會有點難理解,能夠多試幾回,打斷點看看控制檯的調用棧。相信仍是能夠看出其中的原理的
相關文章
相關標籤/搜索