JavaScript异步加载的三种方式——async、defer、动态创建
async和defer
html4.0中定义了defer;html5.0中定义了async。
如果没有defer和async,浏览器会立即加载并执行指定的JS脚本,并不会等待后续载入的文档元素。
如果有async,加载后续文档元素的过程中,将和JS的加载与执行,并行进行(异步)。
如果有defer,加载后续文档元素的过程中,将与JS的加载,并行进行(异步)。但JS的执行,要等到所有的文档元素解析完成之后,DOMContentLoaded事件触发之前完成。
代码如下:
<script async src="/xxx.js"> // async方式加载js文件
<script defer src="/xxx.js"> // defer方式加载js文件
async和defer的共同点:
- 不会阻塞文档元素的加载
- 使用这两个属性的JS脚本中,不能调用document.write方法
- 只适用于外部脚本,把延迟脚本放在页面底部加载是最优选择
async和defer的不同点:
- 每一个async脚本加载完毕后就会立即执行,一定会在window.onload之前执行。但可能会在DOMContentLoaded之前或者之后执行,不能保证顺序。如果JS脚本有依赖性,就需要格外注意,执行异步脚本的目的是不让页面等待脚本的下载和执行,从而异步加载页面的其他内容。因此,建议异步脚本不要在加载期间修改DOM节点。
- 每一个defer脚本都是在文档元素完全载入之后,一般会在DOMContentLoaded之前执行,相当于window.onload,但应用上比window.onload更灵活。
动态创建script
在没有defer和async之前,异步加载的方式是动态创建script标签。
通过window.onload方法来确保页面加载完毕之后,再将script标签插入到页面中。
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.src = src;
document.body.appendChild(script);
}
window.onload = function() {
addScriptTag('./xxx.js');
}