js是单线程执行的,是因为保证只能由一个线程去操作DOM。
模型:

1、执行栈 stack:
execution stack
所有的代码都是在此空间中执行的。
2、堆 heap
对象被分配在堆中,堆是一个用来表示一大块(通常是非结构化的)内存区域的计算机术语。
3、队列callback queue
一个 JavaScript 运行时包含了一个待处理消息的消息队列。每一个消息都关联着一个用以处理这个消息的回调函数。
4、事件循环 event loop:
- 执行初始化代码, 将事件回调函数交给对应模块管理
- 当事件发生时, 管理模块会将回调函数及其数据添加到回调列队中
- 只有当初始化代码执行完后(可能要一定时间), 才会遍历读取回调队列中的回调函数执行
也可以按照如下去理解:
事件循环:
运行时会从最先进入队列的消息开始处理队列中的消息。被处理的消息会被移出队列,并作为输入参数来调用与之关联的函数。正如前面所提到的,调用一个函数总是会为其创造一个新的栈帧。
函数的处理会一直进行到执行栈再次为空为止;然后事件循环将会处理队列中的下一个消息。
之所以称之为 事件循环,是因为它经常按照类似如下的方式来被实现:
while (queue.waitForMessage()) {
queue.processNextMessage();
}
任务队列
所有的任务可以分为同步任务和异步任务,同步任务,顾名思义,就是立即执行的任务,同步任务一般会直接进入到主线程中执行;而异步任务,就是异步执行的任务,比如ajax网络请求,setTimeout定时函数等都属于异步任务,异步任务会通过任务队列(Event Queue)的机制来进行协调。
事件循环 event loop:
同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入Event Queue。主线程内的任务执行完毕为空,会去Event Queue读取对应的任务,推入主线程执行。
浏览器内核
browser core
js引擎模块(在主线程处理)
其它模块(在主/分线程处理)
定时器任务
定时器任务不能保证在设定的时间执行, 会有一点延迟。