async和defer
参考链接:https://github.com/xiaoyu2er/blog/issues/8
两者都会并行下载,下载过程不会影响页面的解析。
普通script
<script src="./test1.js"></script> <script src="./test2.js"></script> <script> document.addEventListener('DOMContentLoaded', () => { console.log('DOMContentLoaded触发了') }) console.log('同步执行代码1') //打印顺序 test1 test2 同步执行代码1 DOMContentLoaded触发了 </script>
- 停止页面解析
- 请求test1.js,执行test1.js脚本
- 请求test2.js,执行test2.js脚本
- 执行script标签中脚本
- 继续页面解析
- 触发DOMContentLoaded事件
async
并行下载,下载完成后立即执行,与DOMContentLoaded事件前后不确定(脚本很小或脚本缓存,并且页面很大的情况,脚本可能在DOMContentLoaded前发生)
适合用在完全不依赖其他脚本的脚本上。
<script src="./test1.js" async></script> <script src="./test2.js" async></script> <script> document.addEventListener('DOMContentLoaded', () => { console.log('DOMContentLoaded触发了') }) console.log('同步执行代码1') //打印顺序 同步执行代码1 DOMContentLoaded触发了 test1 test2 </script>
- 页面解析不会停止,test1.js与test2.js并行下载
- 脚本下载完成后立即执行(两者执行顺序不确定,执行阶段不确定,也可能是在DOMContentLoaded之前执行)
defer
并行下载,下载完成后按照代码顺序在页面解析完成后(所有同步脚本都执行完)但DOMContentLoaded事件发生前执行。
<script src="./test1.js" defer></script> <script src="./test2.js" defer></script> <script> document.addEventListener('DOMContentLoaded', () => { console.log('DOMContentLoaded触发了') }) console.log('同步执行代码1') //打印顺序 同步执行代码1 test1 test2 DOMContentLoaded触发了 </script>
- 页面解析不会停止,test1.js与test2.js并行下载
- 执行‘同步执行代码1’
- 按照test1与test2的位置,在其他同步脚本都执行完后,依次执行test1.js与test2.js
- 触发DOMContentLoaded事件
其他
script标签无src属性,defer与async会被忽略
动态添加的script标签隐含async属性