开发者社区> leonwuv> 正文

HTML5中<script>标签中的defer与async属性详解

简介:    在HTML中执行脚本最重要的方法就是使用<script>元素,但是执行<script>元素时会阻塞后面文档的加载。 那么首先为什么会阻塞呢,是由于哪些原因呢? 其实是<script>标签中的src属性在作怪,因为一个src就相当于一次http请求,他的作用就是把src所对应的地址上的文档下载到本地,因此当浏览器碰到<scrip
+关注继续查看

   在HTML中执行脚本最重要的方法就是使用<script>元素,但是执行<script>元素时会阻塞后面文档的加载。

那么首先为什么会阻塞呢,是由于哪些原因呢?

其实是<script>标签中的src属性在作怪,因为一个src就相当于一次http请求,他的作用就是把src所对应的地址上的文档下载到本地,因此当浏览器碰到<script>标签时,严格的说也就是src时,他会立即停止HTML文档的解析,而去下载并且执行脚本,当脚本执行完毕才会继续解析HTML文档。这就是形成阻塞的原因,

这里不得不提的是,<a>标签中的href属性,它的意义只是把此文档和href后面跟的文档建立连接关系,而不用下载,这就是他与src的区别。

    为了解决这个问题HTML5<script>元素添加了asyncdefer属性。

一、浏览器加载到<script>元素,没有设置async或者defer

<code class="hljs xml has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">script</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">src</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"main.js"</span>></span><span class="javascript" style="box-sizing: border-box;"></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">script</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

       浏览器执行到这个元素的时候会立即下载src所指向的脚本并且执行,在执行完该脚本以后再加载这个<script>元素后面的文档。

二、当浏览器执行到<script>元素,元素设置了async属性

<code class="hljs xml has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">script</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">async</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">src</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"main.js"</span>></span><span class="javascript" style="box-sizing: border-box;"></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">script</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

       当浏览器解析到这个<script>元素的时候,会立即下载该脚本,但是不糊阻塞页面中的其他操作,比如其他脚本的加载和页面的渲染。加载和渲染后续文档的过程和加载main.js并行执行(异步)。

       async不能保证按照脚本出现的先后顺序执行,所以,确保该脚本和其他文档的相互依赖关系非常重要,指定async的目的是让页面不用等待这个脚本加载完毕以后再继续下一步操作,让指定async的脚本和后续文档异步执行,所以设置异步加载的脚本最好不要操作DOM,因为不知道他什么时候执行,容易产生错误。

       async脚本会在页面的load事件之前执行,但是不一定在DOMContentLoaded事件之前执行,有可能在这个事件之前或者之后执行。支持async的浏览器有:Firefox 3.6、Safari 5 和Chrome。

三、当浏览器解析到<script>,元素设置了defer属性

<code class="hljs xml has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">script</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">defer</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">src</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"main_1.js"</span>></span><span class="javascript" style="box-sizing: border-box;"></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">script</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">script</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">defer</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">src</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"main_2.js"</span>></span><span class="javascript" style="box-sizing: border-box;"></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">script</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

       当元素加载到<script>元素,该元素设置了defer时,会立即下载该脚本,但是会延迟执行,加载后续文档的过程会和该脚本并行进行(异步),它会在所有文档解析之后,在DOMContentLoaded事件执行之前完成。和async不同的还有一点是设置了defer的脚本会按照它出现在HTML页面中的顺序执行。

四、总结

       从实际角度出发,还是把<script>放在body的底部比较合适,对于比较旧的浏览器这是最好的优化方式,并且能够保证非脚本的文档以最快的速度解析。

下面来看一张图: 
script 
上图中,绿色代表HTML文档解析; 
蓝色代表网路读取,红色代表执行时间,这两个是针对脚本的。

从上图中我们可以得出以下几点总结:

  1. asyncdefer在网络读取这一部分是一样的,即下载脚本的时候都是异步的。
  2. asyncdefer很明显的差别在于执行时间不同,async在加载完之后就执行,而defer是在页面解析之后执行,显然defer更接近我们对于脚本执行的要求。
  3. 关于defer,图中没有表现出来的是defer是按照顺序执行脚本的。
  4. 关于defer ,并不能保证执行的顺序,它加载和执行是紧紧挨着的,加载完后就立即执行,不管你声明的顺序如何,都不知道它是什么时候执行的。
  5. 因为async不能保证脚本执行的顺序,所以要设置async的脚本一定要和其他脚本没有依赖关系,并且不操作DOM。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
HTML 里 img 元素的 src 和 srcset 属性有何区别?
HTML 里 img 元素的 src 和 srcset 属性有何区别?
8 0
开心档之HTML 属性
【摘要】 HTML 属性属性是 HTML 元素提供的附加信息。HTML 属性HTML 元素可以设置属性属性可以在元素中添加附加信息属性一般描述于开始标签属性总是以名称/值对的形式出现,比如:name="value"。属性实例HTML 链接由 <a> 标签定义。链接的地址在 href 属性中指定:实例<a href="http://www.kxdang.com/topic/">这是一个链接</a>HTM...
9 0
开心档之 HTML 属性
属性是 HTML 元素提供的附加信息。HTML 属性:HTML 元素可以设置属性,属性可以在元素中添加附加信息,属性一般描述于开始标签
7 0
一篇”水文“带你解剖HTML中的ID属性以及和Class属性的区别。
一篇”水文“带你解剖HTML中的ID属性以及和Class属性的区别。
12 0
陪你一起攻破前端,未来打造运维领域B/S架构产品。带你复习巩固HTML常用的元素和属性,看这篇就够了。
陪你一起攻破前端,未来打造运维领域B/S架构产品。带你复习巩固HTML常用的元素和属性,看这篇就够了。
19 0
前端祖传三件套HTML的HTML5之新表单元素和属性 datalist/keygen/output
HTML5 是 Web 技术的重要更新,它引入了许多新特性,其中包括一些新的表单元素和属性。这些新元素和属性使得表单更加方便、灵活,为用户和开发者提供更好的体验。
25 0
HTML表单和CSS属性以及DOM实现网页版计算器
本文讲解:HTML表单和CSS属性以及DOM实现网页版计算器
28 0
HTML 属性
HTML 属性
13 0
开心档之HTML 属性
HTML 属性 HTML 元素可以设置属性 属性可以在元素中添加附加信息 属性一般描述于开始标签 属性总是以名称/值对的形式出现,比如:name="value"。 属性实例 HTML 链接由 <a> 标签定义。链接的地址在 href 属性中指定:
18 0
JavaScript 能够改变 HTML 属性
JavaScript 能够改变 HTML 属性
35 0
+关注
leonwuv
Code is my life!
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
天猫HTML5互动技术实践
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
相关实验场景
更多