1.主要内容
主要内容是讲javascript的执行机制。以及对Event Loop的解释,以下内容中js执行的宿主环境是浏览器端,在nodeJs中某些细微的地方可能会有些差异,但执行机制还是一样的。
2.一些基本概念
javascrip的执行是单线程,也就是一次执行一个任务,多个任务就要一个一个排队执行,但是如果要执行一个耗时很长的任务,那就会阻塞后续代码的执行,因此JS就有了Event Loop机制去实现异步任务。
3.同步代码执行
Javascript引擎(JavaScript Engine)都不陌生,最著名的就是V8了,js引擎就是解释 并执行JS代码的,它一行一行的遍历我们应用程序中的代码,并一次执行一行,所以我们的javascript就是单线程的了, 不会同时执行多行代码。
先来看看同步代码的执行,这里要引入一个调用栈的概念(call stack),可以理解为javascript引擎一行行遍历我们应用程序代码,将遍历到的要执行的那行代码放到执行栈里, 然后执行,执行完后就把这行推出来,再取应用程序中的下一行。
接下来看这么个例子: 例子和图的思想取自文章:What is the JavaScript event loop?。
/*main.js file */
var firstFunction = function () {
console.log("I'm first!");
};
var secondFunction = function () {
firstFunction();
console.log("I'm second!");
};
secondFunction();
接下来js引擎执行main.js文件时call stack执行情况如下:
- main.js的执行,main.js可以看做是一个入口函数执行,此时call stack初始状态为:
- js引擎从上往下遍历,要执行的代码是secondFunction(),将其放入call stack中:
- 放入之后就执行这个函数,这个函数执行又调用了firstFunction(),将其放入执行栈中:
- 执行firstFunction(),控制台输出"I'm first!":
- firstFunction()执行完,移除执行栈:
- 继续执行secondFunction()后面的代码控制台输出"I'm second!":
- secondFunction()执行完毕,移出执行栈:
- main.js执行完了, 移除执行栈。
至此,我们这个只有同步任务的代码已经执行完了,但是如果任务中会有一些耗时很长的任务,那么他将会阻塞后面同步代码的执行,因此接下来就要讲到js中的异步代码的执行了。
5.Event Loop (事件循环机制)
应用从程序中会有很多的异步操作,比如setTimeout,setInterval,ajax的请求等。因此这些异步代码是如何执行同时又不阻塞主线程的运行的呢。

6.含有异步代码的执行
接下来看这么个例子: 例子和图的思想还是取自文章:What is the JavaScript event loop?。
var firstFunction = function () {
console.log("I'm first!");
};
var secondFunction = function () {
setTimeout(firstFunction, 5000);
console.log("I'm second!");
};
secondFunction();
-
第一、二、是和同步一样的,将secondFunction()放入到了call stack中,然后执行,此时需要执行一个异步方法,在setTimeout执行之前是如下情况:
-
setTimeout执行完之后,setTimeout推出call stack回调函数firstFunction会放入到EventTable中。
-
主线程继续执行secondFunction(),控制台输出I'm second!,secondFunction()推出call stack, 此时5s还未到:
-
main.js执行完了,call stack 未空了, 5s还未到:
-
5s时间到了,Event table监听到了这个事件,将对应的回调函数firstFunction放入到Event Queue中:
-
Event Loop机制监控到call stack 为空,且Event Queue有函数firstFunction(),因此将该函数推入新的call stack中开始又一轮的执行:
在主线程的执行过程中,Event table一直会监听是否有特定事件触发,然后将回调放入到Event Queue中。 同时事件循环机制会监控call stack是否为空, 如果为空就会将Event Queue中的回到函数推入一个新的call stack中,重新又开始一轮主线程执行。
7.后记
本文是结合一些其他文章学习以及自己理解的总结性文章,如有不对之处还请轻喷并给予指出,如能无意中对某些小伙伴略有帮助将不甚荣幸!!!!