0

0

浏览器JS执行顺序规则?

畫卷琴夢

畫卷琴夢

发布时间:2025-08-30 15:42:01

|

505人浏览过

|

来源于php中文网

原创

JavaScript单线程执行意味着同一时间只能处理一个任务,导致耗时操作会阻塞页面响应;为优化体验,浏览器通过async和defer属性实现脚本异步加载,避免阻塞HTML解析,其中async脚本下载后立即执行,不保证顺序,而defer脚本在DOM解析完成后按序执行;更复杂的执行顺序由事件循环机制调控,它协调宏任务(如setTimeout)与微任务(如Promise回调),确保微任务优先于宏任务执行,从而形成一套高效、非阻塞的异步编程模型。

浏览器js执行顺序规则?

浏览器中的JavaScript执行,从宏观上看是单线程、同步阻塞的,但现代前端开发中,异步机制(如事件循环、Promise、async/await)和脚本加载优化(如

async
defer
属性)极大地改变了这种简单模型,使得实际的执行顺序变得更为复杂和精妙。它不像我们想象的那么直接,背后有一套精心设计的规则在运作。

要说浏览器里JavaScript的执行顺序,这事儿真不是一两句话能讲清的,它像个层层嵌套的洋葱。最基础的,浏览器在解析HTML文档时,如果遇到

<script>
标签,它会停下来(解析阻塞),先下载脚本,然后执行脚本,执行完了才继续解析HTML。这是最原始、最“粗暴”的同步模式。

但我们都知道,这种阻塞体验太差了,尤其是脚本文件大的时候,页面会白屏很久。所以,后来就有了各种优化手段。比如,把

<script>
标签放到
<body>
底部,这样至少能让HTML结构先渲染出来。再后来,HTML5引入了
async
defer
这两个属性,它们就像给脚本加载和执行开了“绿色通道”,让脚本下载不再阻塞HTML解析。

async
属性的脚本会在下载完成后立即执行,不等待HTML解析,也不保证脚本间的执行顺序。这有点像“谁先到谁先吃”的自助餐。而
defer
属性的脚本则会在HTML解析完成后、
DOMContentLoaded
事件之前,按照它们在文档中出现的顺序依次执行。这更像“排队领餐,但可以提前准备好”。

除了这些加载层面的优化,JavaScript语言本身也进化出了强大的异步能力。事件循环(Event Loop)是理解JS异步执行的关键。它把那些耗时的操作,比如网络请求、定时器、用户交互,从主线程上“剥离”出去,交给Web APIs处理,等结果准备好了,再把回调函数放到任务队列里,等待主线程空闲时去执行。这里面还有微任务(Microtask)和宏任务(Macrotask)的区别,微任务(比如Promise的回调)总是优先于宏任务(比如

setTimeout
的回调)执行,这又是一层精细的调度。

所以,一个页面上,你可能会看到

<script>
标签里的同步代码、
async
加载的脚本、
defer
加载的脚本,以及各种异步操作的回调函数,它们在浏览器这个大舞台上,按照一套复杂的优先级和调度机制,共同编织出最终的执行顺序。这套机制,既保证了用户体验,又让开发者能够编写出高效、响应迅速的应用。

为什么说JavaScript是单线程的,以及它如何影响执行顺序?

JavaScript是单线程的,这个概念初听起来可能有点反直觉,毕竟我们平时用浏览器感觉它能同时做很多事。但这里说的“单线程”特指JS引擎在执行代码时,只有一个主线程负责处理所有的任务。这就意味着,同一时间,它只能做一件事。

这就像一个厨师,他一次只能炒一道菜。如果他正在切菜(执行同步代码),那么他就不能同时洗碗、烧水。一旦有任何一个任务需要长时间运行,比如一个复杂的计算循环,或者一个没有

async
defer
修饰的同步脚本,它就会霸占这个唯一的线程,导致页面卡死,用户界面失去响应——我们常说的“页面冻结”或“卡顿”就是这么来的。

我记得刚开始写前端的时候,就吃过这种亏,一个不小心写了个死循环,整个浏览器标签页就挂了。这深刻说明了单线程的局限性。为了避免这种尴尬,开发者必须学会把耗时的操作“外包”出去,或者拆分成小块,让主线程能定期喘口气,去处理UI渲染、用户输入等其他重要任务。这也是为什么异步编程在JavaScript中如此重要的原因,它不是为了多线程,而是为了在单线程模型下模拟并发,提升用户体验。

async
defer
属性是如何改变脚本加载和执行行为的?

async
defer
这两个属性,对于前端性能优化来说,简直是神来之笔。它们彻底改变了传统
<script>
标签阻塞解析的“霸道”行为。

PaperFake
PaperFake

AI写论文

下载

想象一下,没有

async
defer
时,浏览器遇到
<script src="..."
,就像被点穴一样,必须停下来,下载这个脚本,然后执行它,才能继续往下解析HTML。如果脚本很大,或者网络不好,用户就只能对着一个空白或半成品页面发呆。

有了

async
,脚本的下载是异步的,不阻塞HTML解析。一旦下载完成,它会立即执行。但这里有个关键点:它不会等待HTML解析完成,也不会管其他
async
脚本的顺序。哪个脚本先下载完,哪个就先执行。这对于那些不依赖DOM结构、也不相互依赖的独立脚本(比如统计代码、广告脚本)非常有用,能让它们尽快运行。但如果脚本之间有严格的依赖关系,或者需要操作完整的DOM,
async
就可能导致问题,因为它执行时DOM可能还没解析完,或者依赖的脚本还没加载。

defer
则更“绅士”一些。它的下载也是异步的,不阻塞HTML解析。但它的执行时机有所不同:它会等到整个HTML文档解析完成后,并且在
DOMContentLoaded
事件触发之前,按照它们在文档中出现的顺序依次执行。这意味着,
defer
脚本执行时,DOM已经完全构建好了,而且它们能保证执行顺序。这对于那些依赖DOM结构、并且有明确执行顺序要求的脚本(比如大部分业务逻辑脚本)来说,是更安全、更可靠的选择。

我个人在项目里,如果脚本之间没有明确依赖,或者优先级不高,会倾向于用

async
来争取更快的加载和执行;而对于那些核心业务逻辑、需要操作DOM的脚本,
defer
几乎是我的首选,它能确保一切就绪后再开始工作,避免了很多不必要的运行时错误。

理解JavaScript事件循环(Event Loop)对掌握异步执行顺序有何关键作用?

事件循环(Event Loop),这玩意儿是JavaScript异步编程的“幕后英雄”,也是很多初学者(包括我当年)觉得最烧脑但也最关键的概念。如果你不理解它,那么

setTimeout(..., 0)
为什么不是立即执行,Promise为什么比
setTimeout
优先级高,这些问题就会让你困惑不已。

简单来说,事件循环就是浏览器(或Node.js)用来协调主线程和各种异步任务的一套机制。它由几个核心部分组成:

  1. 调用栈(Call Stack):这是JavaScript主线程执行同步代码的地方,遵循“先进后出”的原则。当一个函数被调用,它就被推入栈中;执行完毕,就被弹出。
  2. Web APIs:这是浏览器提供给JS引擎的一些API,比如
    setTimeout
    fetch
    、DOM事件监听等。当JS代码调用这些API时,它们会被“送”到Web APIs去处理,主线程得以继续执行后续的同步代码,而不会被这些耗时操作阻塞。
  3. 任务队列(Task Queue / Callback Queue / Macrotask Queue):当Web APIs中的异步操作完成时(比如定时器时间到了,网络请求返回了数据),它们对应的回调函数并不会立即回到调用栈执行,而是会被放到这个任务队列里排队。
  4. 微任务队列(Microtask Queue):这是一个特殊的任务队列,专门用来存放微任务,比如Promise的回调(
    .then()
    ,
    .catch()
    ,
    .finally()
    )、
    MutationObserver
    的回调等。它的优先级比宏任务队列高。

事件循环的工作流程大致是这样的:主线程会先清空调用栈中的所有同步代码。一旦调用栈为空,事件循环就开始检查微任务队列。如果有微任务,它会把所有微任务都取出来,逐个推入调用栈执行,直到微任务队列清空。清空微任务队列后,事件循环才会去宏任务队列中取出一个宏任务(比如一个

setTimeout
的回调),推入调用栈执行。执行完毕后,再次检查微任务队列,如此循环往复。

这种机制就解释了为什么

Promise.resolve().then(...)
会比
setTimeout(..., 0)
先执行。因为
Promise
的回调是微任务,而
setTimeout
的回调是宏任务,微任务在每个宏任务执行前,都会被优先清空。理解了这一点,你就能更好地预测和控制异步代码的执行顺序,编写出更健壮、更可控的JavaScript应用。这对于调试复杂的异步逻辑,简直是救命稻草。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

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

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

550

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的相关内容,可以阅读本专题下面的文章。

471

2024.03.06

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

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

297

2025.12.30

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

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

229

2025.12.30

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

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

107

2025.12.30

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

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

165

2025.12.31

HTML5建模教程
HTML5建模教程

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

53

2025.12.31

html5怎么使用
html5怎么使用

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

73

2025.12.31

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

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

精品课程

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

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.3万人学习

Java 教程
Java 教程

共578课时 | 81.8万人学习

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

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