Javascript 调用setTimeout是否清除调用堆栈?

Javascript 调用setTimeout是否清除调用堆栈?,javascript,settimeout,callstack,Javascript,Settimeout,Callstack,通过使用setTimeout方法调用函数而不是直接调用函数,可以避免javascript中的堆栈溢出吗?我对setTimeout的理解是,它应该启动一个新的调用堆栈。当我查看chrome和IE的调用堆栈时,似乎setTimeout调用正在等待函数调用返回 这只是调试器的属性还是我的理解有缺陷 编辑 虽然下面提供的答案是正确的,但我遇到的实际问题与调用setTimeout(affunction(),10)有关,因为括号的缘故,setTimeout正在立即计算函数。帮我整理一下。异步调用,比如来自s

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

这只是调试器的属性还是我的理解有缺陷

编辑


虽然下面提供的答案是正确的,但我遇到的实际问题与调用setTimeout(affunction(),10)有关,因为括号的缘故,setTimeout正在立即计算函数。帮我整理一下。

异步调用,比如来自
setTimeout
的调用,确实会生成一个新的调用堆栈


当你说“当我查看chrome和IE的调用堆栈时,似乎setTimeout调用正在等待函数调用返回”时,你并不完全清楚你在描述什么。但是,你可以做的一件事是在由
setTimeout
调用的函数内放置一个断点,然后查看调用堆栈是否为空。

我可以确认堆栈是否已清除

考虑以下情况:

function a() {
     b();   
}

function b() {
     c();   
}

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

function d() {
    debugger;
}

a();
因此有两个断点-一个在函数
c
的开头,另一个在函数
d
的开头

在第一个断点处堆栈:

  • c()
  • b()
  • ()
在第二个断点处堆栈:

  • d()

实时演示:

还有另一种方法可以在不使用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)
$node testLoop.js
{‘运行时(秒)’:20.647399601}
C:\Users\jlowe\Documents\Projects\clearStack\testLoop.js:25
抛出错误('退出')
^
错误:退出
反对。(C:\Users\jlowe\Documents\Projects\clearStack\testLoop.js:25:11)
at模块编译(内部/modules/cjs/loader.js:776:30)
在Object.Module._extensions..js(internal/modules/cjs/loader.js:787:10)
at Module.load(内部/modules/cjs/loader.js:653:32)
在tryModuleLoad(内部/modules/cjs/loader.js:593:12)
at Function.Module._load(内部/modules/cjs/loader.js:585:3)
位于Function.Module.runMain(internal/modules/cjs/loader.js:829:12)
启动时(内部/bootstrap/node.js:283:19)
在bootstrapNodeJSCore(internal/bootstrap/node.js:622:3)

您知道为什么我仍然可以在调试器中看到整个调用堆栈吗?是因为我从setTimeout调用的函数使用闭包获取某些局部变量吗?@AranMulholland在哪里调用调试器?在传递到
setTimeout
?@ŠimeVidas的函数中,根据问题,我只是在查看浏览器调试器(Chrome和IE)中的调用堆栈。如果你说他们生成了一个新的调用堆栈,那么这个家伙说它可能还必须在回调队列中等待,这是错的吗?youtu.be/8aGhZQkoFbQ?t=782调用堆栈和回调(任务)队列是完全不相关的概念。在调用的函数返回之前,不能调用传递到
setTimeout
中的函数。因此,是的,该函数确实启动了一个新的调用堆栈。感谢您为我指明了正确的方向,我能够根据您的答案解决问题,但是我还有另一个问题,看看这个人是否正确,您的答案怎么可能是正确的答案?因为这家伙说它总是首先将回调推送到回调队列,而不是堆栈,所以如果调用堆栈中仍有同步命令在运行,或者堆栈中的其他东西,它必须等待甚至超过指定的毫秒。所以它并不总是1:1。这可能会发生:嘿,我给了你5秒的延迟,为什么你7秒后回来?因为回调需要再等一会儿。您通过
setTimeout
的第二个参数指定的延迟并不保证在该特定时间点调用回调,true;但是我的回答并没有说会。我认为需要注意的是,
d()
将在一个单独的调用堆栈中以
c()
的范围调用。因此,当执行
d()
时,虽然
c()
已经完成了到
a()
的所有过程,但它们的局部变量仍然保留在内存中,直到
d()
完成,GC开始清理空间。