在了解javascript运行机制前 我们需要了解一下以下几点:
javascript是多线程还是单线程?
一个简单的测试
javascript中的 同步任务与异步任务
javascript中的 执行栈
javascript中的回调函数和事件
Javascript中的任务队列
javascript中的Event Loop
javascript是多线程还是单线程?
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。
一个简单的测试,思考一下 以下代码 的运行结果
function syncAndAsync() {
console.log("1") //步骤1
setTimeout(() => {//步骤3
console.log("2")
}, 1000);
console.log("3")//步骤2
}
运行结果:1,3,2
为什么 是这样的结果呢?
如果把步骤2的时间改为0秒 结果会如何呢?
请读完js的运行机制后 ,答案就很明了了。
javascript中的同步任务与异步任务
因为javascript是单线程的 ,所以 javascript 把运行的任务,设计了两种 同步任务和异步任务
同步任务指的是:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务指的是:不进入主线程、被主线程挂起的任务,只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。当主线程 的所有同步任务执行完后,查看该任务队列 的事件,对应的任务 结束等待状态,进入执行栈,开始执行。
javascript中的 执行栈
所有同步任务都是在主线程上执行的,这些同步任务在主线程上的执行,这就是执行栈。
javascript中的回调函数
回调函数,就是那些会被主线程挂起来的任务。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
Javascript中的任务队列
"任务队列"是一个事件的队列(也可以理解成消息的队列),队列中对应的任务有了结果(比如读取文件(io操作),请求远程数据等等),就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有那些事件。
"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。
javascript中的Event Loop
主线程先执行同步任务,也就是执行栈中的 任务,当执行完所有的执行栈中的任务后 ,从"任务队列"中读取事件,然后执行对应可执行状态的异步任务(回调)。这个过程是不断循环的,所以整个的这种运行机制又称为Event Loop(事件循环)。
异步执行的运行机制步骤如下:
1,所有同步任务都在主线程上执行,形成一个执行栈(execution context stack),排队执行。
2,主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
3,一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
4,主线程不断重复上面的第三步。