返回

浏览器中的JS执行机制,从一道执行题看透门道

前端

浏览器中的JS执行机制

JavaScript(JS)是一种流行的编程语言,常用于前端开发。JS代码在浏览器中执行,浏览器会根据JS执行机制来决定代码的执行顺序和时机。

同步任务和异步任务

JS代码可以分为同步任务和异步任务。同步任务会在主线程上顺序执行,一个同步任务执行完后,才会执行下一个同步任务。异步任务不会阻塞主线程,可以在主线程执行的同时在其他线程中执行。

WebAPI

WebAPI是浏览器提供的一系列API,允许JS代码与浏览器进行交互,例如发起网络请求、操作DOM元素、设置定时器等。当JS代码调用WebAPI时,浏览器会将该任务交给其他线程处理,而主线程可以继续执行其他任务。

回调队列和执行栈

浏览器有一个执行栈和一个回调队列。执行栈用于存放正在执行的同步任务,回调队列用于存放等待执行的异步任务。当执行栈中的同步任务执行完毕后,浏览器会从回调队列中取出一个异步任务放入执行栈中执行。

JS代码的执行流程

当浏览器遇到一段JS代码时,会先将其解析成AST(抽象语法树),然后将AST编译成字节码。字节码会被解释器解释执行,解释器会将字节码逐行读取并执行。

异步编程的原理

异步编程是利用JS的事件循环机制来实现的。事件循环机制是指浏览器会不断循环执行以下步骤:

  1. 检查执行栈中是否有同步任务。
  2. 如果有同步任务,则执行该任务。
  3. 如果执行栈中没有同步任务,则检查回调队列中是否有异步任务。
  4. 如果有异步任务,则将该任务放入执行栈中执行。
  5. 重复步骤1-4,直到执行栈和回调队列都为空。

一道执行题

现在,让我们以一道执行题来加深对JS执行机制的理解。

console.log('1');

setTimeout(() => {
  console.log('2');
}, 0);

console.log('3');

当浏览器执行这段代码时,会先将代码解析成AST,然后将AST编译成字节码。字节码会被解释器解释执行,解释器会将字节码逐行读取并执行。

首先,解释器会执行第一行代码console.log('1'),这会将字符串'1'输出到控制台。

然后,解释器会执行第二行代码setTimeout(() => {console.log('2')}, 0). 这行代码会创建一个定时器,该定时器会在0毫秒后执行回调函数() => {console.log('2')}

需要注意的是,定时器是一个异步任务,它不会阻塞主线程。因此,解释器会继续执行第三行代码console.log('3'),这会将字符串'3'输出到控制台。

接下来,定时器会在0毫秒后执行回调函数() => {console.log('2')} 。此时,主线程已经执行完了所有的同步任务,因此,回调函数会被放入回调队列中。

当执行栈中的同步任务都执行完毕后,浏览器会从回调队列中取出一个异步任务放入执行栈中执行。因此,回调函数() => {console.log('2')} 会被放入执行栈中执行,这会将字符串'2'输出到控制台。

总结

通过这道执行题,我们可以看到JS代码的执行顺序是怎样的。同步任务会在主线程上顺序执行,异步任务不会阻塞主线程,可以在主线程执行的同时在其他线程中执行。浏览器会根据JS执行机制来决定代码的执行顺序和时机。