<script>标签的执行

2023/03/26

<script>标签本身的加载和整体执行属于宏任务,它的执行过程可能包含同步任务和异步任务,会阻塞HTML解析和渲染,所以建议<script>写在</body>前。网页性能优化的手段还有<script>标签中的defer、async属性,用于控制脚本的异步加载和执行行为。

一、defer与async对比

deferasync
异步加载不阻塞HTML解析,脚本在后台下载不阻塞HTML解析,脚本在后台下载
执行时机HTML文档完全解析完成,DOM树构建完毕后,但在DOMContentLoaded事件之前执行,脚本在文档中的按照出现顺序执行脚本一旦下载完成就立即执行(如果HTML解析已完成,则立即执行;如果HTML解析未完成,暂停解析,执行脚本,然后继续解析),多个async脚本的执行顺序取决于下载完成顺序
DOMContentLoaded在所有defer脚本执行完成后才会触发DOMContentLoaded事件不等待async脚本执行完成就可能触发DOMContentLoaded事件
适用场景有依赖关系或需要操作DOM的脚本独立无依赖的脚本(如统计代码)

二、注意事项

1.defer仅对外部脚本有效

<script defer>console.log('defer会被忽略');</script>

2.动态添加的脚本默认具有async行为

const script = document.createElement('script');
script.src = 'c.js';
document.body.appendChild(script);

3.模块脚本默认具有defer行为

<script type="module" src="xxx.js"></script>

4.兼容性

IE10+完全支持,更旧浏览器会忽略defer,退化为同步执行。