JavaScript 标签加载
目录
- JavaScript 标签加载
- script 标签的 async 和 defer 属性,分别代表什么,有什么区别
- 1. 普通 script 标签
- 2. async 属性
- 3. defer 属性
- 4. type="module"
- 5. 各种加载方式的对比
- 6. 使用建议
JavaScript 标签加载
script 标签的 async 和 defer 属性,分别代表什么,有什么区别
标准答案:
1. 普通 script 标签
<script src="script.js"></script>
- 加载和执行都会阻塞 HTML 解析
- 按照在文档中的顺序执行
- 在全局作用域中执行
- 可以访问全局变量和函数
- 不支持跨域加载(除非设置 CORS)
2. async 属性
<scriptasyncsrc="script.js"
></script>
- 异步加载脚本,不阻塞 HTML 解析
- 加载完成后立即执行,可能会中断 HTML 解析
- 适用于独立脚本,如第三方统计、广告等
- 执行顺序不保证,谁先加载完谁先执行
- 在全局作用域中执行
- 可以访问全局变量和函数
- 不支持跨域加载(除非设置 CORS)
3. defer 属性
<scriptdefersrc="script.js"
></script>
- 异步加载脚本,不阻塞 HTML 解析
- 等待 HTML 解析完成后,DOMContentLoaded 事件前执行
- 多个 defer 脚本按照在文档中的顺序执行
- 适用于需要操作 DOM 或依赖页面结构的脚本
- 在全局作用域中执行
- 可以访问全局变量和函数
- 不支持跨域加载(除非设置 CORS)
4. type=“module”
<scripttype="module"src="script.js"
></script>
- 异步加载脚本,不阻塞 HTML 解析
- 默认具有 defer 属性,等待 HTML 解析完成后执行
- 支持 ES6 模块系统,可以使用 import/export
- 严格模式(‘use strict’)下执行
- 具有自己的作用域,不会污染全局作用域
- 支持跨域加载(需要设置 CORS)
- 只能通过 HTTP(S) 协议加载,不能通过 file:// 协议加载
- 模块只会被加载一次,即使多次引用也只会执行一次
- 模块加载顺序按照 import 语句的顺序执行
5. 各种加载方式的对比
特性 | 普通 script | async | defer | type=“module” |
---|---|---|---|---|
加载方式 | 同步 | 异步 | 异步 | 异步 |
执行时机 | 立即执行 | 加载完立即执行 | HTML 解析完成后执行 | HTML 解析完成后执行 |
执行顺序 | 按文档顺序 | 不保证顺序 | 按文档顺序 | 按 import 顺序 |
作用域 | 全局 | 全局 | 全局 | 模块作用域 |
严格模式 | 可选 | 可选 | 可选 | 强制 |
跨域支持 | 需要 CORS | 需要 CORS | 需要 CORS | 需要 CORS |
协议要求 | 无 | 无 | 无 | 必须 HTTP(S) |
模块支持 | 不支持 | 不支持 | 不支持 | 支持 |
重复加载 | 会重复执行 | 会重复执行 | 会重复执行 | 只执行一次 |
6. 使用建议
-
普通 script:
- 适用于简单的脚本
- 需要立即执行的脚本
- 对加载顺序有严格要求的脚本
-
async:
- 适用于独立的第三方脚本
- 不依赖 DOM 的脚本
- 统计、分析等工具脚本
-
defer:
- 适用于需要操作 DOM 的脚本
- 依赖页面结构的脚本
- 需要按顺序执行的脚本
-
type=“module”:
- 适用于现代 JavaScript 应用
- 需要模块化的代码
- 需要严格作用域的代码
- 需要代码复用的场景