0

0

技术解答之JavaScript的执行机制

WBOY

WBOY

发布时间:2022-01-14 17:23:17

|

1526人浏览过

|

来源于掘金

转载

本篇文章带大家带来了javascript中执行机制的相关问题,不论是工作还是面试,我们可能都经常会碰到需要知道代码的执行顺序的场景,希望对大家有帮助。

技术解答之JavaScript的执行机制

进程与线程

我们都知道计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,统领整个计算机硬件;应用程序则是具有某种功能的程序,程序是运行于操作系统之上的。

进程

立即学习Java免费学习笔记(深入)”;

进程是一个具有独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体 进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。

进程具有的特征:

  • 动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;

  • 并发性:任何进程都可以同其他进程一起并发执行;

  • 独立性:进程是系统进行资源分配和调度的一个独立单位;

  • 结构性:进程由程序、数据和进程控制块三部分组成。

线程

线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成。

进程与线程的区别

  • 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;

  • 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;

  • 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号),进程与进程之间互不可见;

  • 调度和切换:线程上下文切换比进程上下文切换要快得多。

JS为什么是单线程?

JavaScript从它诞生之初就是作为浏览器的脚本语言,主要用来处理用户交互以及操作DOM,这就决定了它只能是单线程的,否则会带来非常复杂的同步问题。

举个例子: 如果JS是多线程的,其中一个线程要修改一个DOM元素,另外一个线程想要删除这个DOM元素,这时候浏览器就不知道该听谁的。所以为了避免复杂性,从一诞生,JavaScript就被设计成单线程。

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质

浏览器原理

作为前端工程师,浏览器想必都不陌生,并且浏览器是多进程的。

浏览器组成部分

  • 用户界面:包括地址栏,前进/后退/刷新/书签

  • 浏览器引擎:在用户界面和呈现引擎之间传送指令

  • 渲染引擎:用来绘制请求的内容

  • 网络:用来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作

  • JavaScript解释器:用来解析执行JavaScript代码

  • 用户界面后端:用于绘制基本的窗口小部件,比如组合框和窗口,底层使用操作系统的用户接口

  • 数据存储:属于持久层,浏览器在硬盘中保存类似cookie的各种数据,HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术

注意:与大多数浏览器不同的是,谷歌(Chrome)浏览器的每个标签页都分别对应一个呈现引擎实例。每个标签页都是一个独立的进程

浏览器包含哪些进程

浏览器进程

  • 浏览器的主进程(负责协调、主控),该进程只有一个

  • 负责浏览器界面显示,与用户交互。如前进,后退等

  • 负责各个页面的管理,创建和销毁其他进程

  • 将渲染(Renderer)进程得到的内存中的Bitmap(位图),绘制到用户界面上

  • 网络资源的管理,下载等

第三方插件进程

负责管理第三方插件

GPU进程

负责3D绘制与硬件加速(最多一个)

渲染进程

负责页面文档解析,执行与渲染

渲染进程包含哪些线程

GUI渲染线程

主要负责解析HTML,CSS,构建DOM树,布局,绘制等

该线程与JavaScript引擎线程互斥,当执行JavaScript引擎线程时,GUI渲染线程会被挂起,当任务队列空闲时,主线程才会执行GUI渲染

JavaScript引擎线程

主要负责处理JavaScript脚本,执行代码(如V8引擎)

浏览器同时只能有一个JS引擎线程在运行JS程序,即JS是单线程的

JS引擎线程与GUI渲染线程是互斥的,所以JS引擎会阻塞页面渲染

定时触发器线程

负责执行定时器函数(setTimeout,setInterval)

浏览器定时计数器并不是由JS引擎计数的(因为JS是单线程的,如果处于阻塞状态就会影响计数器的准确性)

通过单独线程来计时并触发定时(计时完毕后,添加到事件触发线程的事件队列中,等待JS引擎空闲后执行),这个线程就是定时触发器线程,也叫定时器线程

W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms

事件触发线程

负责将准备好的事件交给JS引擎线程执行

百家CMS微商城
百家CMS微商城

百家CMS微商城从诞生开始,就坚持着简单实用的原则,基于目前最流行的WEB2.0的架构(php+mysql),拥有成熟、稳定的微电商技术解决方案。基于完整的会员等级制度,完善的微商城购物流程,订单管理、优惠券、搜索、购物车等功能。采用跨平台机制,可同时对接微信公众号平台和支付宝服务窗,兼容微博、手机QQ等平台;丰富的支付方式、支持微信支付、支付宝支付、货到付款、余额支付、网银支付等。并且拥有完整的

下载

当事件被触发时,该线程会把对应的事件添加到待处理队列的队尾,等待JS引擎处理

异步请求线程

在XMLHttpRequest连接后浏览器会开一个线程

检测请求状态变更时,如果有对应的回调函数,异步请求线程就会产生状态变更事件,并把对应的回调函数放入队列中等待JS引擎执行

同步与异步

由于JavaScript是单线程的,这就决定了它的任务不可能只有同步任务,那些耗时很长的任务如果也按同步任务执行的话将会导致页面阻塞,所以JavaScript任务一般分为两类:

同步任务

同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

异步任务

异步任务指的是,不进入主线程、而进入"任务队列"(Event queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

常见的异步任务: 定时器,ajax,事件绑定,回调函数,promise,async await等

  • 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。

  • 当Event Table中指定的事情完成时,会将这个函数移入Event Queue。

  • 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。

  • 上述过程会不断重复,也就是常说的Event Loop(事件循环)。

  • 我们不禁要问了,那怎么知道主线程执行栈为空啊?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。

宏任务与微任务

JavaScript除了广义上的同步任务与异步任务,还有更精细的任务定义:

  • 宏任务(macro-task): 包括全局代码,setTimeout,setInterval

  • 微任务(micro-task): new Promise().then(回调) process.nextTick()

不同类型的任务会进入到不同的任务队列:

22.png

事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。

执行栈与任务队列

执行栈

JavaScript代码都是在执行上下文中执行的,在JavaScript中有三种执行上下文:

  • 全局执行上下文

  • 函数执行上下文,JS函数被调用时都会创建一个函数执行上下文

  • eval执行上下文,eval函数产生的上下文(用的较少)

通常来说我们的JS代码都不止一个上下文,那么这些上下文的执行顺序是怎样的呢?

我们都知道栈是一种后进先出的数据结构,我们JavaScript中的执行栈就是一种这样的栈结构,当JS引擎执行代码时,会产生一个全局上下文并把它压入执行栈,每当遇到函数调用时,就会产生函数执行上下文并压入执行栈。引擎从栈顶开始执行函数,执行完后会弹出该执行上下文。

function add(){
  console.log(1)
  foo()
  console.log(3)
}
function foo(){
  console.log(2)
}
add()

我们来看下上面这段代码的执行栈是怎样的:

23.png

任务队列

前面我们说到了JavaScript中所有的任务分为同步任务与异步任务,同步任务,顾名思义就是立即执行的任务,它一般是直接进入到主线程中执行。而我们的异步任务则是进入任务队列等待主线程中的任务执行完再执行。

任务队列是一个事件的队列,表示相关的异步任务可以进入执行栈了。主线程读取任务队列就是读取里面有哪些事件。

队列是一种先进先出的数据结构。

上面我们说到异步任务又可以分为宏任务与微任务,所以任务队列也可以分为宏任务队列与微任务队列

  • Macrotask Queue:进行比较大型的工作,常见的有setTimeout,setInterval,用户交互操作,UI渲染等;

  • Microtask Queue:进行较小的工作,常见的有Promise,Process.nextTick;

事件循环(Event-Loop)

同步任务直接放入到主线程执行,异步任务(点击事件,定时器,ajax等)挂在后台执行,等待I/O事件完成或行为事件被触发。

系统后台执行异步任务,如果某个异步任务事件(或者行为事件被触发),则将该任务添加到任务队列,并且每个任务会对应一个回调函数进行处理。

这里异步任务分为宏任务与微任务,宏任务进入到宏任务队列,微任务进入到微任务队列。

执行任务队列中的任务具体是在执行栈中完成的,当主线程中的任务全部执行完毕后,去读取微任务队列,如果有微任务就会全部执行,然后再去读取宏任务队列

上述过程会不断的重复进行,也就是我们常说的事件循环(Event-Loop)。

24.png

例题验证

我们来看道题目进行验证

(async ()=>{
    console.log(1) 
  
    setTimeout(() => {
    console.log('setTimeout1')
    }, 0);
  
    function foo (){
        return new Promise((res,rej) => {
            console.log(2)
            res(3)
        })
    }
  
    new Promise((resolve,reject)=>{
    console.log(4)
    resolve() 
    console.log(5)
    }).then(()=> {
    console.log('6')
    })
  
    const res = await foo();
    console.log(res);
    console.log('7')
  
    setTimeout(_ => console.log('setTimeout2'))
})()

打印顺序是:1,4,5,2,6,3,7,setTimeout1,setTimeout2

分析:

代码自上而下执行,先遇到console.log(1),直接打印1,接着遇到定时器属于宏任务,放入宏任务队列

再遇到promise,由于new Promise是一个同步任务,所以直接打印4,遇到resolve,也就是后面的then函数,放入微任务队列,再打印5

然后再执行await foo,foo函数里面有个promise,new promise属于同步任务,所以会直接打印2,await返回的是一个promise的回调,await后面的任务放入微任务队列

最后遇到一个定时器,放入宏任务队列

执行栈任务执行完了,先去微任务队列获取微任务执行,先执行第一个微任务,打印6,再执行第二个微任务,打印3,7

微任务执行完,再去宏任务队列获取宏任务执行,打印setTimeout1,setTimeout2

【相关推荐:javascript学习教程

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
html5动画制作有哪些制作方法
html5动画制作有哪些制作方法

html5动画制作方法有使用CSS3动画、使用JavaScript动画库、使用HTML5 Canvas等。想了解更多html5动画制作方法相关内容,可以阅读本专题下面的文章。

512

2023.10.23

HTML与HTML5的区别
HTML与HTML5的区别

HTML与HTML5的区别:1、html5支持矢量图形,html本身不支持;2、html5中可临时存储数据,html不行;3、html5新增了许多控件;4、html本身不支持音频和视频,html5支持;5、html无法处理不准确的语法,html5能够处理等等。想了解更多HTML与HTML5的相关内容,可以阅读本专题下面的文章。

436

2024.03.06

html5从入门到精通汇总
html5从入门到精通汇总

想系统掌握HTML5开发?本合集精选全网优质学习资源,涵盖免费教程、实战项目、视频课程与权威电子书,从基础语法到高级特性(Canvas、本地存储、响应式布局等)一应俱全,适合零基础小白到进阶开发者,助你高效入门并精通HTML5前端开发。

69

2025.12.30

html5新老标签汇总
html5新老标签汇总

HTML5在2026年持续优化网页语义化与交互体验,不仅引入了如<header>、<nav>、<article>、<section>、<aside>、<footer>等结构化标签,还新增了<video>、<audio>、<canvas>、<figure>、<time>、<mark>等增强多媒体与

105

2025.12.30

html5空格代码怎么写
html5空格代码怎么写

在HTML5中,空格不能直接通过键盘空格键实现,需使用特定代码。本合集详解常用空格写法:&nbsp;(不间断空格)、&ensp;(半个中文空格)、&emsp;(一个中文空格)及CSS的white-space属性等方法,帮助开发者精准控制页面排版,避免因空格失效导致布局错乱,适用于新手入门与实战参考。

78

2025.12.30

html5怎么做网站教程
html5怎么做网站教程

想从零开始学做网站?这份《HTML5怎么做网站教程》合集专为新手打造!涵盖HTML5基础语法、页面结构搭建、表单与多媒体嵌入、响应式布局及与CSS3/JavaScript协同开发等核心内容。无需编程基础,手把手教你用纯HTML5创建美观、兼容、移动端友好的现代网页。附实战案例+代码模板,快速上手,轻松迈出Web开发第一步!

158

2025.12.31

HTML5建模教程
HTML5建模教程

想快速掌握HTML5模板搭建?本合集汇集实用HTML5建模教程,从零基础入门到实战开发全覆盖!内容涵盖响应式布局、语义化标签、Canvas绘图、表单验证及移动端适配等核心技能,提供可直接复用的模板结构与代码示例。无需复杂配置,助你高效构建现代网页,轻松上手前端开发!

29

2025.12.31

html5怎么使用
html5怎么使用

想快速上手HTML5开发?本合集为你整理最实用的HTML5使用指南!涵盖HTML5基础语法、主流框架(如Bootstrap、Vue、React)集成方法,以及无需安装、直接在线编辑运行的平台推荐(如CodePen、JSFiddle)。无论你是新手还是进阶开发者,都能轻松掌握HTML5网页制作、响应式布局与交互功能开发,零配置开启高效前端编程之旅!

42

2025.12.31

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

11

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号