v8引擎是否首先填充调用堆栈,然后运行代码?还是一进入函数就运行代码



这是我尝试过的代码:

// **Creating variables and functions**
let number_object = { num: 0 }
function doHomework(callback) {     //Starts doing the homework, supposed to finish after 5 seconds
console.log("writing")
setTimeout(() => {
callback()
}, 5000)
}
function Finished() {        //Called when 5 seconds are over
console.log("Finished the homework")
}
function loop_(num_object) {  
++num_object.num;
let i = 0;
for (i = 0; i < 3000000000; ++i) { }
console.log(`loop number ${num_object.num} over`)
}
// **Calling functions now**
doHomework(Finished)
let i = 0;
for (i = 0; i < 10000000000; ++i) { }  //This takes much more than 5 seconds
console.log(`This took more than 5 seconds, yet "finished" is not going to appear next`)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)

输出为:

writing
This took more than 5 seconds, yet "finished" is not going to appear next
loop number 1 over
loop number 2 over
loop number 3 over
loop number 4 over
loop number 5 over
loop number 6 over
loop number 7 over
loop number 8 over
loop number 9 over
loop number 10 over
Finished the homework

因此,我认为输出表明,代码首先将调用堆栈中的所有函数排队,然后运行它们。这就是为什么所有的10个函数都在调用堆栈中排队,所以只有在它们完成之后;成品";出现

这被称为在再次进入事件循环之前运行到完成。

代码首先将调用堆栈中的所有函数排队,然后运行它们。这就是为什么所有10个函数都在调用堆栈中排队的原因

否,这10个函数没有在调用堆栈上排队。它们是";排队的";在程序代码中,如果有的话。只是你的大量增量操作不会在任何地方排队。它们被编码在程序中,然后运行。

重要的是要记住,setTimeout不会NOT调用您传递给它的函数。相反,它会保存一个指针,指向javascript稍后在超时时将调用的函数。

从这个意义上讲,javascript与Java、C/C++、Pascal、Python等没有什么不同。在所有这些语言中,如果将函数指针保存到链接/列表或数组,则在稍后调用该函数之前,不会调用该函数。唯一的区别是,带有回调的API是javascript内置的标准库的一部分。可以肯定的是,这样的API在其他语言中也存在,尤其是在GUI编程时。

就调用堆栈而言,javascript的行为通常与C/C++完全相同,但当涉及闭包时,它确实会变得奇怪。有了闭包,javascript的调用堆栈的行为类似于Lisp/Scheme、Haskell、Swift或Python。

事件循环

需要注意的是,javascript是单线程的(有些人可能会声称不是这样——他们错了(。解释器的结构通常如下:

// Pseudocode
script_to_execute = compile_scripts();
event_handlers = [];
do {
scheduled_callbacks = execute(script_to_execute)
for each (callback in scheduled_callbacks) {
event_handlers.push(callback)
}
event = wait_for_async_events()
for each (callback in event_handlers) {
if (callback.event == event) {
script_to_execute = callback.script
}
}
}
while (event_handlers.length > 0)

因此,基本上,对setTimeout的调用会将这些函数添加到事件处理程序列表中。您的整个脚本最初位于script_to_execute中。如果您查看上面的程序流,很明显,只要您的脚本仍在执行,就不会处理任何事件。因此,javascript中的所有异步操作,包括setTimeout、HTTP请求、DOM更新等,都只会发生在脚本的最后一行之后。

正如您所看到的,所有这些都与调用堆栈或作用域无关。这只是时间安排——有些事情只是在未来发生,而不是现在。

相关内容

最新更新