实际上,你的代码并没有创建一个无限循环。它会一直打印数字1,直到5秒钟过去为止。我在本地进行了测试,虽然打印速度很快,看起来像是无限循环,但实际上只要你向下滚动到控制台底部,就会发现打印最终会停止。你可以尝试将时间设置为500毫秒来观察效果。
let a = Date.now() + 500;
while(Date.now() < a) {
console.log(1);
}
console.log("finished");
对于setTimeout为何仍能正常工作的问题,你需要理解JavaScript的内部运行机制。我推荐你观看这个视频:How JavaScript Works 🔥& Execution Context
在JavaScript中,所有需要执行的函数会被推送到调用栈(call stack)中进行执行。在这个例子中,while循环中的console.log
方法就是如此。
同时,JavaScript引擎还有一个回调队列(callback queue),其中包含等待执行的回调函数,并且有一个事件循环(event loop)始终检查调用栈是否为空。如果调用栈为空(意味着可以执行下一个函数),事件循环就会从回调队列中取出一个回调函数并将其推入调用栈进行执行。
在这里,setTimeout
函数有一个回调函数,一旦定时器到期,这个回调函数就会被推送到回调队列中。
你的while循环不断地将console.log
推送到调用栈中快速执行。
但只要回调队列中有待执行的回调函数,并且调用栈在某个时刻变为空(即准备好执行另一个函数时),事件循环就会立即将回调函数推入调用栈执行,并从队列中移除。这个过程会持续下去,直到队列中的所有回调函数都被执行完毕。
所以,在执行顺序上,回调函数具有更高的优先级。你也可以尝试使用多个setTimeout进行实验。
希望这有助于你理解这个问题。