Javascript 头几次执行setTimeout()所需的浏览器时间少于4毫秒

Javascript 头几次执行setTimeout()所需的浏览器时间少于4毫秒,javascript,performance,asynchronous,settimeout,performance-testing,Javascript,Performance,Asynchronous,Settimeout,Performance Testing,在从“You Don't Know JS”学习异步和性能时,我尝试了以下小代码片段: var t = []; var c = 1; function foo() { t.push((performance.now()).toString()); if (c < 50) { setTimeout(foo, 0); c++; } } var t=[]; var c=1; 函数foo(){ t、 push((performance.now()).toString(

在从“You Don't Know JS”学习异步和性能时,我尝试了以下小代码片段:

var t = [];
var c = 1;

function foo() {
  t.push((performance.now()).toString());
  if (c < 50) {
    setTimeout(foo, 0);
    c++;
  }
}
var t=[];
var c=1;
函数foo(){
t、 push((performance.now()).toString());
如果(c<50){
setTimeout(foo,0);
C++;
}
}
最初几次,浏览器(我使用的是chrome)调用
foo
所用的时间少于
4ms
。后来,只花了
4ms
多一点时间

我想问,尽管在创建任务时被设置为
setTimeout()
,但为什么它在最初的3-4次中表现得像microtask

请帮帮我,
谢谢。

为了回答这个问题,
setTimeout()
就是一个使用的例子。微任务是指在每个函数运行之后、消息队列启动之前发生的任何事情。微任务队列实际上是唯一的队列,但从
v8
起,它就被赋予了一个新名称

仅仅因为任务在
4ms
下执行,并不意味着它是一个微任务。我举了一个例子,其中第二个样本采集了
5ms

你发现这个有趣趋势的原因很可能是Chrome的优化。最初的几次调用几乎是立即完成的,随着调用堆栈的增长,它会深入挖掘以获取更多的RAM

if (c < 50) {
  setTimeout(foo, 10);
  c++;
}
if(c<50){
设置超时(foo,10);
C++;
}

如果您尝试上面的代码片段,您会注意到时间戳要一致得多。这是因为调用堆栈的添加间隔更为固定。

您所说的“微任务”是什么意思?事实上,我不太明白你的问题。您只需运行一个异步函数,它将在下一个事件周期中执行。微小的时间差异可能有多种原因,因为JS是在浏览器中执行的,所有操作都由浏览器自己完成,后台调用,缓存等会影响结果。在javascript中,微任务是在不到4ms的时间内执行的任务,而不是进入下一个事件周期。例如,promise.then()是microtask。microtask是一个概念,它与执行的特定时间长度无关(即,仅仅因为它小于4ms,并不意味着它是一个microtask)。具体来说,微任务是属于作业队列而不是常规调用堆栈的任何内容:如果使用
setTimeout(fn,0)
避免堆栈溢出,请参阅。