我们知道,当浏览器在执行到script标签的时候,首先会停止构建DOM树,然后下载Javascript文件并且执行,当JavaScript脚本执行完毕之后才会继续解析HTML标签构建DOM树。
为什么Javascript程序会这样做呢?
原因是我们的Javascript的作用就是操作DOM并且可以修改DOM。如果我们等到HTML执行完成之后再去执行JavaScript就会造成严重的回流和重绘,尤其是现代化编程中大部分用的都是Vue和React框架。页面都是由Javascript来渲染页面的,十分影响网页性能。所以在渲染DOM树的情况下,当遇到Javascript都会先下载然后执行,再渲染DOM树。
为了解决这个问题,JavaScript语言的script标签给了我们两个属性:defer属性和async属性。
defer的作用是什么?
defer属性告诉我们,让页面不要等待JavaScript语言下载,而是继续执行HTML构建DOM树。脚本会由浏览器来执行下载,这个过程不会阻塞构建DOM树。如果脚本下载好了,他会等待DOM树构建好了,在DOMContentLoaded事件执行之前执行JavaScript程序defer中的代码。如下图:

所以反过来说,DOMContentLoaded事件总会等待defer中的代码执行完毕之后再运行。还有值得一提的是当页面中有多个script标签中有defer属性的时候,它会根据标签的先后顺序依次进行。所以defer属性推荐放到script标签中,并且最好放在head标签中。
为什么最好放在head标签中呢?因
为DOM树构建的过程中,会按照标签的先后顺序执行,假如我们将带defer属性的script标签放到最后。其实不会有多大效果,从内存的角度来说就是带defer属性的script标签相当于给我们的代码新增了一个线程来执行代码。当然不影响DOM树的构建。这里我们考虑到了下载JavaScript代码也是需要时间的。不如放在head标签中增加效率。
感谢大家观看
async属性是什么?它有什么作用? - 前端程序员,PHP程序员,全栈程序员-程序员鸡皮 游客 2026-03-08 22:40 回复
[...]async属性和defer属性目标一样它也是为了不让js阻塞DOM树的构建。不过他们两个还是有区别的。async让js脚本的下载和执行是独立的。浏览器不会因为async属性的script脚本的执行而阻塞,这一点和defer属性类似。然而async属性比较任性,只要脚本被浏览器下载完成之后就会立即执行,不会等待在DOMContentLoaded之前执行。所以它不能保证是在DOMContentLoad[...]