2011-11-08 73 views
11

可以通過使用setTimeout方法調用函數而不是直接調用它來避免JavaScript中的堆棧溢出問題?我對setTimeout的理解是,它應該開始一個新的調用堆棧。當我查看chrome和IE的callstack時,似乎setTimeout調用正在等待函數調用返回。調用setTimeout清除調用堆棧嗎?

這只是調試器的屬性或我的理解有缺陷?

編輯

儘管下面提供的答案是正確的,我是有實際問題涉及的事實,我打電話這是因爲立即評估機能缺失的setTimeout(機能缺失(),10)括號。 This question把我排序。

+0

傳遞到'setTimeout'功能無法在調用'setTimeout'返回函數之前被調用。所以是的,該功能確實啓動了一個新的調用堆棧。 –

回答

12

我可以證實,堆棧被清除。

考慮這種情況:

function a() { 
    b(); 
} 

function b() { 
    c(); 
} 

function c() { 
    debugger; 
    setTimeout(d, 1000); 
} 

function d() { 
    debugger; 
} 

a(); 

因此有兩個斷點 - 一個在功能c開始,一個在功能d開始。

堆棧在第一斷點:

  • C()
  • B()
  • 一個()

堆棧在第二斷點:

  • d()

現場演示:http://jsfiddle.net/nbf4n/1/

+0

感謝您指出我在正確的方向,我能夠根據您的答案解決,但我有另一個問題請參閱http://stackoverflow.com/questions/8058996/why-does-calling-settimeout-with-parenthesis- not-start-a-new-callstack –

+0

如果這個人是正確的,你的答案怎麼能是正確的答案?因爲這個人說它總是首先將你的回調推回到回調隊列中,而不是堆棧,所以如果在調用堆棧中仍然有同步命令運行,或者堆棧中的其他東西,它必須等待超過指定的毫秒。所以它並不總是1:1。這可能會發生:嘿,我給你5秒延遲你爲什麼要回來7?因爲回調不得不再等一會兒。 https://youtu.be/8aGhZQkoFbQ?t=782 – PositiveGuy

+0

您通過'setTimeout'的第二個參數指定的延遲並不能保證在該特定時間點調用回調,true;但我的回答並沒有說它會。 –

4

異步調用,如來自setTimeout,確實產生了新的調用堆棧。

這不是完全清楚你描述當你說「當我在Chrome和IE瀏覽器的調用堆棧看起來似乎setTimeout的呼叫等待功能調用返回。」但是,您可以做的一件事是在setTimeout調用的函數內部放置一個斷點,並查看該調用堆棧是否爲空。

+0

你知道爲什麼我仍然可以在調試器中看到整個調用堆棧嗎?是否因爲我的函數調用setTimeout使用閉包來獲得某些局部變量? –

+1

@AranMulholland你在哪裏調用調試器?傳遞給'setTimeout'的函數內部? –

+0

@ŠimeVidas按的問題,我只是希望在瀏覽器調試器(Chrome和IE) –