我理解的 JavaScript EventLoop
在学习JavaScript的事件循环(event loop)的过程中,遇到了调用栈(call stack)的概念。阅读了若干资料,对此概念感觉更加清晰了。在此记录并分享一下自己的理解。
强调一下
首先,需要“咬文嚼字”一下,“调用栈”,应该更加精确的描述为“函数调用栈”,因为此概念所涉及的就是关于函数调用过程的,而不其他代码的执行过程,所以强调一下。
解释器对函数调用的大概过程
- 当代码调用一个函数,解释器将此函数放入 call stack 栈顶,然后开始执行此函数。
- 任何在函数中调用的函数,会被继续堆砌到 call stack 栈顶,然后执行。(每当遇到函数调用此过程会不断进行)。(此过程会构造出一个 栈(LIFO))。
- 任何一个函数执行完毕后,都会被从 call stack 栈顶移除。解释器会回到此函数被调用的地方继续执行。(每当函数执行完毕,此过程会不断进行)
- 函数执行过程中构建的call stack (栈) 如果超过,解释器定义的栈的容量,会出现堆栈溢出错误(stack overflow)。
javascript是单线程 single thread: 简单来说就是,代码只能一行(逻辑行)一行的执行,同一时间只能做一件事情。因为js是单线程的,所以它不能阻塞,因为这等于整个程序都暂停运行。那么在浏览器中,我们是如何去执行并发的去执行任务的呢?并发的任务是交给浏览器去做的,这时就需要事件机制。js可以注册事件回调,这个注册的过程会立即返回,不会阻塞js代码的执行。这个回调函数,会被添加到 “事件表”中。当回调对应的事件被触发后,回调函数会被推入到,解释器的消息队列中(message queue)(FIFO)。当,之前提到过的 call stack 为空后,解释器会从 消息队列中,取出并从队列中移除,队头的函数,放入ß call stack 中,然后执行,执行完毕后,从call stack中移除。然后,每当call stack 为空时,就会检查消息队列中是否有函数,如果有就放入 call stack 执行。