< script >标签中的 async 和 defer 属性都是用来控制外部 JavaScript 文件的加载和执行时机的。它们的目的是优化页面加载性能,避免脚本的加载和执行阻塞页面的渲染过程。下面是 async 和 defer 两个属性的用途和它们之间的区别。

Async (异步)

当在< script >标签中使用 async 属性时,浏览器会在后台异步加载 JavaScript 文件,不会阻塞 HTML 文档的解析。即使 JavaScript 文件下载完成,只要 HTML 解析还未结束,脚本不会立即执行。只有在文件加载完成后,它才会尽快执行,无论 HTML 解析是否完成。这意味着 async 脚本的执行时机是不确定的,可能会在文档解析完成前或完成后。

Defer (延迟)

当你在< script >标签中使用 defer 属性时,浏览器也会异步加载 JavaScript 文件,但会延迟执行这个脚本,直到整个页面的 HTML 都解析完成。这确保了脚本只会在文档解析完成之后、在 DOMContentLoaded 事件之前执行。如果有多个带有 defer 属性的脚本,它们将按照在文档中出现的顺序被执行。

区别
执行时机:

async : 一旦脚本异步加载完成,就会尽快执行,这可能在 HTML 文档解析完成前或完成后。

defer : 脚本会在整个 HTML 文档解析完成后、 DOMContentLoaded 事件触发前按顺序执行。

脚本顺序:

async : 多个带 async 的脚本不能保证按照它们在页面中出现的顺序执行。

defer : 多个带 defer 的脚本会按照它们在页面中出现的顺序执行。

使用 async 或 defer 的最佳实践取决于脚本的性质和需求。如果脚本相互独立,或者其执行顺序无关紧要,则可以使用 async 。如果脚本的执行需要保证顺序,尤其是当脚本之间有依赖时,应当使用 defer 。对于那些需要尽快加载并执行的脚本(例如性能监测脚本),可能不适合使用这两个属性。