1. 引言
<script> 元素是 HTML 中用于嵌入或引用 JavaScript 代码的核心标签。无论是简单的页面交互,还是复杂的前端应用,都离不开它。本文将系统讲解 <script> 元素的用法、属性、加载策略以及常见实践,帮助你写出更高效、更健壮的网页脚本。
2. 基本用法
<script> 元素有两种主要使用方式:内联脚本 和外部脚本。
2.1 内联脚本
直接在 HTML 文件中写入 JavaScript 代码:
html
<script>
console.log("Hello, World!");
</script>
2.2 外部脚本
通过 src 属性引用外部的 .js 文件:
html
<script src="js/app.js"></script>
注意 :使用外部脚本时,
<script>标签内的代码会被忽略,因此不要同时使用src属性和内联代码。
3. 常用属性
<script> 元素支持多个属性,用于控制脚本的加载和执行行为。
| 属性 | 说明 |
|---|---|
src |
指定外部脚本文件的 URL |
type |
指定脚本类型,默认是 text/javascript;使用模块时设为 module |
async |
异步加载脚本,加载完成后立即执行(仅适用于外部脚本) |
defer |
延迟执行脚本,在文档解析完成后、DOMContentLoaded 事件前执行(仅适用于外部脚本) |
crossorigin |
设置跨域请求的 CORS 配置 |
integrity |
子资源完整性(SRI)校验,防止脚本被篡改 |
nomodule |
在支持 ES 模块的浏览器中不执行该脚本 |
4. 加载与执行策略
脚本的加载方式直接影响页面性能,理解 async 与 defer 的区别至关重要。
4.1 默认行为(阻塞)
默认情况下,浏览器在解析到 <script> 标签时会暂停 HTML 解析,先下载并执行脚本,然后再继续解析。这会导致页面渲染被阻塞。
html
<!-- 会阻塞页面解析 -->
<script src="js/app.js"></script>
4.2 defer(延迟执行)
defer 属性让脚本在后台下载,同时不阻塞 HTML 解析。脚本会在文档解析完成后按顺序执行。
html
<script defer src="js/app.js"></script>
4.3 async(异步执行)
async 属性让脚本在后台下载,下载完成后立即执行,不保证执行顺序,也不等待 HTML 解析完成。
html
<script async src="js/analytics.js"></script>
4.4 对比总结
| 属性 | 下载时机 | 执行时机 | 执行顺序 |
|---|---|---|---|
| 无 | 解析到即下载 | 下载完立即执行(阻塞解析) | 按文档顺序 |
defer |
解析时后台下载 | 文档解析完成后 | 按文档顺序 |
async |
解析时后台下载 | 下载完立即执行 | 不保证顺序 |
5. 模块脚本
使用 type="module" 可以将脚本作为 ES 模块加载,支持 import 和 export 语法。
html
<script type="module">
import { greet } from "./utils.js";
greet("World");
</script>
模块脚本默认启用严格模式 ,并且具有延迟执行 的特性,即使不加 defer 也会在文档解析完成后执行。
6. 放置位置建议
6.1 传统做法:放在 <body> 末尾
将脚本放在 <body> 结束标签之前,可以确保 DOM 已解析完成,避免操作不存在的元素。
html
<body>
<!-- 页面内容 -->
<script src="js/app.js"></script>
</body>
6.2 现代做法:放在 <head> 中配合 defer
将脚本放在 <head> 中并添加 defer 属性,既不影响解析,又能提前开始下载。
html
<head>
<script defer src="js/app.js"></script>
</head>
7. 常见问题与最佳实践
7.1 脚本报错:找不到元素
如果脚本在 DOM 解析完成前执行,可能找不到目标元素。解决方案:
- 将脚本放在
<body>末尾; - 使用
defer或async; - 监听
DOMContentLoaded事件。
html
<script>
document.addEventListener("DOMContentLoaded", function () {
const btn = document.getElementById("btn");
btn.addEventListener("click", handleClick);
});
</script>
7.2 使用 SRI 增强安全性
通过 integrity 属性校验脚本完整性,防止 CDN 脚本被篡改。
html
<script
src="https://cdn.example.com/js/lib.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"
></script>
7.3 避免阻塞渲染
对于非关键脚本(如统计代码),使用 async 或 defer,避免阻塞首屏渲染。
8. 总结
<script> 元素是 HTML 与 JavaScript 之间的桥梁。掌握它的基本用法、属性含义以及加载策略,是写出高性能网页的关键一步。在实际开发中,建议:
- 优先使用外部脚本,便于缓存和维护;
- 使用
defer处理依赖 DOM 的脚本; - 使用
async加载独立、非关键的脚本; - 使用模块脚本组织复杂的前端逻辑。
希望本文能帮助你更好地理解和使用 <script> 元素,写出更高效、更可靠的网页。