调用setTimeout是否清除了callstack?

时间:2011-11-08 23:45:09

标签: javascript settimeout callstack

使用setTimeout方法调用函数而不是直接调用函数,可以在javascript中避免堆栈溢出吗?我对setTimeout的理解是它应该启动一个新的callstack。当我查看chrome和IE的callstack时,似乎setTimeout调用正在等待函数调用返回。

这只是调试器的属性还是我的理解存在缺陷?

修改

虽然下面提供的答案是正确的,但我遇到的实际问题与我调用setTimeout(aFunction(),10)的事实有关,因为括号因此立即评估aFunction。 This question将我排除在外。

3 个答案:

答案 0 :(得分:15)

我可以确认堆栈已清除。

考虑这种情况:

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/

答案 1 :(得分:5)

异步调用(例如来自setTimeout的异步调用)确实会生成新的callstack。

当你说“当我查看chrome和IE的callstack时,看起来setTimeout调用正在等待函数调用返回时,你所描述的内容并不完全清楚。”但是,你可以做的一件事是在setTimeout调用的函数中放置一个断点,并看到callstack是空的。

答案 2 :(得分:0)

还有另一种无需使用setTimeout()即可清除调用堆栈的方法:

testLoop.js

let counter = 0;
const max = 1000000000n  // 'n' signifies BigInteger
Error.stackTraceLimit = 100;

const A = () => {
  fp = B;
}

const B = () => {
  fp = A;
}

let fp = B;

const then = process.hrtime.bigint();

loop:   // label is not needed for this simple case though useful for some cases
for(;;) {
  counter++;
  if (counter > max) {
    const now = process.hrtime.bigint();
    const nanos = now - then;

    console.log({ "runtime(sec)": Number(nanos) / (1000000000.0) })
    throw Error('exit')
  }
  fp()
  continue loop;
}

输出:

$ node testLoop.js
{ 'runtime(sec)': 20.647399601 }
C:\Users\jlowe\Documents\Projects\clearStack\testLoop.js:25
    throw Error('exit')
    ^

Error: exit
    at Object.<anonymous> (C:\Users\jlowe\Documents\Projects\clearStack\testLoop.js:25:11)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)