不加async和defer属性的加载和执行
-
Attributes 的基本概念
- 在 HTML 中,“attributes”(属性)是用于为 HTML 标签提供额外信息的一种机制。对于
<script>标签来说,属性可以改变脚本的加载、执行行为以及和其他元素的交互方式等诸多特性。
- 在 HTML 中,“attributes”(属性)是用于为 HTML 标签提供额外信息的一种机制。对于
async
defer
-
概念理解
defer属性:script标签中的defer属性用于告诉浏览器这个脚本文件应该在文档解析完成后、DOMContentLoaded事件触发之前执行。可以把它想象成一个 “延迟执行但有序” 的指令。当浏览器遇到带有defer属性的script标签时,会继续解析 HTML 文档,构建 DOM 树,等 HTML 解析完成后,再按照script标签在文档中出现的顺序依次执行这些脚本。async属性:async属性则表示脚本是异步执行的。浏览器在遇到带有async属性的script标签时,会在后台继续解析 HTML 的同时,开始下载并执行这个脚本。脚本的执行顺序不确定,谁先下载完成谁就先执行,它更像是一种 “谁快谁先跑” 的机制。
-
加载和执行顺序对比
- 假设有三个脚本文件
script1.js、script2.js和script3.js,在 HTML 文件中有如下script标签设置:
- 假设有三个脚本文件
<script defer src="script1.js"></script>
<script src="script2.js"></script>
<script async src="script3.js"></script>
-
对于
script2.js(没有defer和async属性),浏览器会按照文档流的顺序,在解析到这个script标签时,停止 HTML 解析,先下载并执行script2.js,然后再继续解析后面的 HTML。 -
script1.js(带有defer属性)会在整个 HTML 文档解析完成后,按照它在文档中的顺序(在这个例子中是第一个)来执行,而且它的执行一定是在DOMContentLoaded事件触发之前。 -
script3.js(带有async属性)会在浏览器发现这个标签后,和 HTML 解析同时进行下载。一旦下载完成,就会立刻执行,不管 HTML 是否解析完成,也不考虑它在文档中的顺序。所以script3.js有可能在script1.js和script2.js之前、之间或者之后执行。
-
对页面渲染的影响
defer属性:使用defer属性的脚本不会阻塞 HTML 文档的解析,这使得页面能够更快地构建 DOM 树,用户可以更快地看到页面的基本结构。因为脚本是在文档解析完成后才执行,所以可以确保脚本在操作 DOM 时,DOM 已经构建完成,不会出现找不到元素等问题。这种方式适用于那些依赖完整 DOM 结构的脚本,如对 DOM 元素进行事件绑定、初始化等操作的脚本。async属性:async属性的脚本同样不会阻塞 HTML 文档的解析(在下载阶段),但是由于它的执行顺序不确定,可能会在 DOM 尚未完全构建好的时候就开始执行。这可能会导致脚本在访问某些尚未创建的 DOM 元素时出现错误。它比较适合那些不依赖于页面 DOM 结构,或者可以在任何时候执行而不影响页面功能的脚本,比如一些统计代码、广告脚本等,这些脚本主要是发送数据给服务器,对页面的渲染和交互不是特别依赖。
-
使用场景推荐
-
defer的推荐场景:- 当脚本用于初始化页面组件、添加事件监听器,并且这些操作需要完整的 DOM 结构时,使用
defer是很好的选择。例如,一个 JavaScript 函数用于给页面中的所有按钮添加点击事件,这个脚本应该使用defer,这样可以确保在执行这个函数时,所有的按钮元素都已经在 DOM 中存在。 - 对于多个相互依赖的脚本,并且需要按照一定顺序执行,
defer也很合适。因为它能保证脚本按照在文档中的顺序执行,这样可以避免因执行顺序混乱而导致的错误。
- 当脚本用于初始化页面组件、添加事件监听器,并且这些操作需要完整的 DOM 结构时,使用
-
async的推荐场景:- 对于一些不依赖于页面 DOM 结构,只是用于收集数据、发送统计信息的脚本,如 Google Analytics 脚本等,
async是理想的选择。这些脚本的主要目的是在后台发送数据,即使在页面还在渲染或者部分脚本还未执行的情况下,它们也可以正常工作。 - 当对脚本的执行顺序没有严格要求,并且希望脚本尽快执行以减少页面加载时间(因为它不等待文档解析完成就可以开始下载和执行)时,也可以使用
async。例如,一些独立的小工具脚本,它们之间没有相互依赖关系,并且对页面的渲染和交互影响较小。
- 对于一些不依赖于页面 DOM 结构,只是用于收集数据、发送统计信息的脚本,如 Google Analytics 脚本等,
-
END
defer和anysc是script标签中用于控制脚本加载和执行顺序的两个重要属性,它们在优化网页性能和确保脚本正确执行方面发挥着关键作用。