2011-09-02 48 views
0

我猜它停止由達夫代碼瀏覽器越來越釘所有的時間,但這樣的:JavaScript中遞歸的限制是多少?

 function print(item) { 
      document.getElementById('output').innerHTML = 
       document.getElementById('output').innerHTML 
       + item + '<br />'; 
     } 

     function recur(myInt) { 
      print(myInt); 
      if (int < 10) { 
       for (i = 0; i <= 1; i++) { 
        recur(myInt+1); 
       } 
      } 
     } 

生產:

0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
10 

,而不是大的老惹我得到當我這樣做:

 function recur(myInt) { 
      print(myInt); 
      if (int < 10) { 
       for (i = 0; i <= 1; i++) { 
        var x = myInt + 1; 
        setTimeout("recur("+x+")"); 
       } 
      } 
     } 

我錯過了什麼,或者這是如何做JS遞歸?我有興趣使用遞歸來導航樹,您需要爲每個孩子調用方法。

+1

'如果(int <10)'會失敗if塊並停止遞歸。這是任何語言的預期行爲。 – jiggy

+1

請避免命名變量「int」。雖然它在js中可能是合法的,但這是令人困惑的,因爲它是許多其他語言中的保留字。 –

+0

該方法的兩個版本應該返回相同的代碼,然後他們不會第二個產生大量的數字,因爲我期望該方法自動調用兩次。對於(i = 0; i <= 1; i ++), – gordatron

回答

4

你正在使用一個全局變量作爲循環計數器,這就是爲什麼它只爲最內層調用完全循環。當你從那個呼叫返回時,計數器已經超出了所有其他循環的循環結束。

如果你把一個局部變量:

function recur(int) { 
    print(int); 
    if (int < 10) { 
     for (var i = 0; i <= 1; i++) { 
      recur(int + 1); 
     } 
    } 
} 

輸出相同數量的項目使用超時時。使用超時時,全局變量不會導致相同的問題,因爲遞歸調用會排隊並稍後執行,此時您已退出循環。

+0

優秀!謝謝!我知道我錯過了一些東西......我之前在那裏有var,但由於某種原因,我將它刪除了! – gordatron

+0

愚蠢,因爲我認爲當我拿出的var,這將把它放在全球範圍不會它..啊,我還在學習JS ;-) – gordatron

1

遞歸在JavaScript中很少受到限制。除非你的樹很深,否則應該沒問題。大多數樹,即使有數百萬個元素,也是相當廣泛的,所以在堆棧上最多可以獲得log(n)遞歸調用,這絕不是一個問題。當然不需要setTimeout。就像在你的第一個例子中一樣,你是對的,有時你需要一個守衛子句來保證遞歸最終落空。

+0

這不涉及範圍問題,這是他難度的根源 – antlersoft

2

我知道你做錯了什麼。函數中的遞歸保持了一定的範圍,所以每當循環運行一次時,你的迭代器(i)實際上正在增加每個範圍。

function recur(int) { 
      print(int); 
      if (int < 10) { 
       for (var i = 0; i <= 1; i++) { 
        recur(int+1); 
       } 
      } 
     } 

請注意,現在'var i = 0'這會阻止迭代器覆蓋彼此。在設置超時時,它允許第一個循環在運行其餘部分之前完成運行,它也將從窗口對象運行,這可能會刪除最後一個迭代器的關閉。