【问题标题】:Why does calling setTimeout with parenthesis not start a new callstack?为什么用括号调用 setTimeout 不会启动新的调用堆栈?
【发布时间】:2011-12-24 22:21:27
【问题描述】:

当调试器在 d (jsfiddle here) 中触发时,以下代码有一个新的调用堆栈

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

function d() {
    debugger;   
}

c();

如果我们修改代码以使用带有括号(括号:)的setTimeout( d(), 1000 );

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

function d() {
    debugger;   
}

c();

然后调用堆栈同时具有 c() 和 d() (jsfiddle here)。为什么?

【问题讨论】:

  • d 计算为函数对象。在函数对象上使用函数应用运算符()(由d 的评估产生)立即调用它并评估所述函数的结果(在这种情况下未定义),然后将其传递为setTimeout 的参数。也就是说,它等价于:var r = d(); setTimeout(r, 1000);,或者在本例中为d(); setTimeout(undefined, 1000)
  • @Aran:这是完全相同的问题,尽管表述方式不同。立即函数调用与将帧推入调用堆栈而另一个仍处于活动状态的帧相同。调用堆栈的提及仅根据特定的计算模型提出问题。如果有的话,这是对问题的更有限的陈述。
  • @outis 我仍然认为这是一个有效的问题,并且以不止一种方式提出问题只会扩大对问题空间的更好理解的可能性。我一直在寻找一种方法来启动一个新的调用堆栈,我最终更好地理解了 setTimeout。一旦你知道答案,你就可以把它看作是重复的,在此之前它是完全不同的,并且与不同的问题有关。

标签: javascript settimeout callstack


【解决方案1】:

在第二个示例中,您没有将setTimeout 传递给函数d;你正在传递d(),这是调用d的结果。

调用d 的结果是undefined,因为它什么都不返回,它转换为字符串"undefined",然后是evaled,做......什么都没有。


关于调用堆栈,由于您在c 内部调用d,这就是您在调用堆栈中看到c 的原因。为了澄清,你的第二个例子是一样的

function c() {
    var temp = d();
    setTimeout(temp, 1000);
}

function d() {
    debugger;   
}

c();

【讨论】:

    【解决方案2】:

    SetTimeout 接受一个函数参数。如果你传递一个字符串,它就像 eval 一样。如果您像以前一样调用该函数,它会立即触发,然后 setTimeout 触发并将结果放入一个新的调用堆栈中。

    【讨论】:

      【解决方案3】:

      因为在第一个示例中,您将函数指针作为要在 1 秒内执行的内容传递。在第二个示例中,您已经执行了 d,并将 d() 的结果传递给 setTimeout,以便在 1 秒内调用。

      【讨论】:

        猜你喜欢
        • 2011-12-24
        • 2018-05-15
        • 1970-01-01
        • 2014-08-29
        • 1970-01-01
        • 2021-04-28
        • 2014-11-13
        • 2021-05-10
        相关资源
        最近更新 更多