2012-05-10 52 views
0

以下代碼段演示了使用JavaScript的遞歸調用。JavaScript中的遞歸效果

function timedCount() 
{ 
document.getElementById('txt').value=c; 
c=c+1; 
t=setTimeout("timedCount()",1000); 
} 

該來源是從here

我的問題:這不會導致堆棧建立和隨後的堆棧溢出嗎?我知道一個事實,這肯定會在像Pascal和C/C++這樣的語言中崩潰。

感謝您對此的任何建議。

回答

2

這不是真正的遞歸,因此不會創建深層調用堆棧。


然而,你應該永遠傳遞一個字符串,setInterval()setTimeout()。這樣做與使用eval()一樣糟糕,只要使用變量,就會導致潛在的不可讀和可能不安全的代碼,因爲您需要將它們插入到字符串中,而不是傳遞實際變量。

適當的解決方案是setTimeout(function() { /* your code *) }, msecs);。這同樣適用於setInterval()。如果你只是想調用一個函數不帶任何參數,您也可以直接傳遞函數名:setTimeout(someFunction, msecs);(注意有沒有()函數名後)

所以你的情況,使用

+0

這是不對的。兩件事情都不一樣。 setInterval將在每次調用之間強制執行一個msecs時間,但僞遞歸setTimeout將防止兩次執行在msecs內發生衝突,如果要執行的代碼的持續時間必須超過msecs,則可能會導致多個同時執行。 – glmxndr

+0

@subtenante:我在哪裏告訴他使用'setInterval()'?!這是兩種情況下的通用文本,我甚至用「setTimeout」給了他一個例子。但我會更新它以使其清晰。 – ThiefMaster

+0

@ThiefMaster我很欣賞使用回調的概念。我更加熱衷於遞歸程序。 從我所知道的,一個調用自己的函數是遞歸。你怎麼說這不是?再次感謝! – itsols

1

這不是遞歸,因爲你的timedCount()功能不調用本身,它呼籲setTimeout()問JS調用timeCount()異步指定的延遲之後。 setTimeout()之後的行(在這種情況下僅僅是函數的結尾)將立即執行,它不會暫停或休眠,直到超時。因此,當您在代碼timedCount()中的其他地方撥打timedCount()將完成執行並且控制將返回到您的代碼的其他部分,則稍後該函數將再次通過超時被調用,這又會導致另一個被調度以供稍後執行(等無限廣告)。在任何時候都沒有中途完成timedCount()等待另一個完成執行,就像實際遞歸一樣。

如果你這樣做:

function timedCount() { 
    // other code here 

    timedCount(); 
} 

...然後將遞歸和的確會崩潰,因爲沒有設定停止遞歸的條件。如果你添加一些控制邏輯,以便遞歸停止一個「合理」的深度級別,那很好。

+0

我想到了我收到的第一個答案。但你的解釋也很好。 +1爲您的努力和時間。謝謝! – itsols