读过本文章后,您能知道:javascript
首先经过一段代码来验证你是否了解代码输出顺序,若是你不知道输出顺序,那么本文能够帮助你了解:html
console.log(1) setTimeout(function () { new Promise(function (resolve) { console.log(2) resolve() }) .then(() => { console.log(3) }) }) setTimeout(function () { console.log(4) }) console.log(5)
JavaScript语言的执行是单线程(single thread)的。java
所谓的单线程,就是指一次只执行一个任务,若是有多个任务,就必须排队,前面一个任务完成,才能执行后面任务。node
这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等待,会拖延整个程序的执行。常见的浏览器无响应(假死),每每就是由于某一段JavaScript代码长时间运行(好比死循环),致使整个页面卡在这个地方,其余任务没法执行。web
为了解决这个问题,JavaScript语言将任务的执行模式分红两种:同步(Synchronous)和异步(Asynchronous)。面试
同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。ajax
异步任务:不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务能够执行了,该任务才会进入主线程执行。chrome
JavaScript执行机制:segmentfault
一、全部同步任务都在主线程上执行,造成一个执行栈(execution context stack)。
二、主线程以外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
三、一旦"执行栈"中的全部同步任务执行完毕,系统就会读取"任务队列",若是有有执行任务,则进入执行栈,开始执行。
四、主线程不断重复上面的三步,此过程也就是常说的Event Loop(事件循环)。
当咱们调用一个方法的时候,js会生成一个与这个方法相对应的执行环境,也叫执行上下文,这个执行环境存在着这个方法的私有做用域、参数、this对象等等。由于js是单线程的,同一时间只能执行一个方法,因此当一系列的方法被依次调用的时候,js会先解析这些方法,把其中的同步任务按照执行顺序排队到一个地方,这个地方叫作执行栈。api
JavaScript是单线程的,那么这个单线程就成为主线程。而事件循环在主线程执行完执行栈代码后,才执行的。因此主线程代码执行时间过长,会阻塞事件循环的执行。只有当执行栈为空的时候(同步代码执行完毕),才会执行事件循环来观察有哪些事件回调须要执行,当事件循环检测到任务队列有事件就读取出回调放到执行栈由主线程执行。
任务队列也有时称叫消息队列、回调队列。
异步操做会将相关回调添加到任务队列中。而不一样的异步操做添加到任务队列的时机也不一样,如onclick, setTimeout,ajax处理的方式都不一样,这些异步操做是由浏览器内核的webcore来执行的,webcore包含下图中的3种 webAPI,分别是DOM Binding、network、timer模块。
如上图所示,JavaScript总体执行过程:
也能够参考以下连接:https://html.spec.whatwg.org/...
出现Promise后,JavaScript对于任务的定义除了广义的同步任务和异步任务,又对任务作了更精细的定义,macrotask(宏任务)和 microtask(微任务):
注意:宏任务、微任务中出现的nodejs中的方法是nodejs专有的,浏览器的JavaScript环境暂时没有支持。
有了宏任务和微任务后,JavaScript事件循环对此处理方法以下形式:
注意::此处把执行同步代码算成第一个宏任务了。
以下代码:
console.log('1'); setTimeout(function() { console.log('2'); new Promise(function(resolve) { console.log('3'); resolve(); }).then(function() { console.log('4') }) }) console.log('5'); setTimeout(function() { console.log('6'); new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { console.log('8') }) }) console.log('9');
上面代码执行过程:
第一轮事件循环
第二轮事件循环
注意:浏览器环境JavaScript的执行机制和node中JavaScript的执行机制是不一样的。