<script> HTML 脚本元素
> HTML <script> 元素用于嵌入可执行代码或数据;通常用来嵌入或引用 JavaScript 代码。<script> 元素也可用于其他语言,例如 WebGL 的 GLSL 着色器编程语言和 JSON。
属性
该元素包含全局属性。
async-
对于经典脚本,若存在
async属性,则会在解析过程中并行获取该经典脚本,并在可用后尽快对其求值。对于模块脚本,若存在
async属性,则会在解析过程中并行获取脚本及其所有依赖项,并在它们可用后尽快执行。警告:对于经典脚本,缺少
src属性(即内联脚本)时不得使用此属性;在这种情况下它不起作用。此属性可消除阻塞解析器的 JavaScript:浏览器本来必须先加载并执行脚本,才能继续解析。
defer在此情形下有类似作用。若同时指定此属性和
defer属性,该元素的行为等同于只指定async属性。这是一个布尔属性:元素上存在布尔属性表示真值,不存在表示假值。
有关浏览器支持的说明,请参见浏览器兼容性。另请参阅 asm.js 的异步脚本。
attributionsrc-
指定希望浏览器在脚本资源请求中一并发送
Attribution-Reporting-Eligible标头。服务器端可据此在响应中发送Attribution-Reporting-Register-Source或Attribution-Reporting-Register-Trigger标头,以分别注册基于 JavaScript 的归因来源或归因触发器。应返回哪种响应标头取决于触发注册的Attribution-Reporting-Eligible标头的值。备注:也可以通过发送包含
attributionReporting选项的fetch()请求(直接在fetch()调用中设置,或在传给fetch()调用的Request对象中设置),或者发送一个在请求对象上调用setAttributionReporting()的XMLHttpRequest,注册基于 JavaScript 的归因来源或触发器。此属性有两种可设置的形式:
-
布尔值,即仅使用
attributionsrc名称。这表示希望将Attribution-Reporting-Eligible标头发送至src属性所指向的同一服务器。当在同一服务器上处理归因来源或触发器注册时,这种形式适用。注册归因触发器时,此属性为可选;若省略,则使用空字符串值。 -
包含一个或多个 URL 的值,例如:
html<script src="myscript.js" attributionsrc="https://a.example/register-source https://b.example/register-source"></script>当所请求资源不在你控制的服务器上,或只想在另一台服务器上处理归因来源注册时,此形式很有用。可将一个或多个 URL 指定为
attributionsrc的值。发生资源请求时,除资源源站外,Attribution-Reporting-Eligible标头也会发送至attributionSrc中指定的 URL。这些 URL 随后可视情况以Attribution-Reporting-Register-Source或Attribution-Reporting-Register-Trigger标头响应,以完成注册。备注:指定多个 URL 意味着可在同一功能上注册多个归因来源。例如,你可能有多个要衡量成效的不同活动,它们需要基于不同数据生成不同报告。
更多信息请参见归因报告 API。
-
blocking-
此属性明确指出,在脚本执行前应阻塞某些操作。要阻塞的操作必须是以空格分隔的阻塞令牌列表。目前仅有一个令牌:
render:阻塞屏幕上内容的渲染。
备注:只有文档
<head>中的script元素才可能阻塞渲染。脚本默认不阻塞渲染;若script元素不含type="module"、async或defer,它阻塞的是解析而非渲染。若通过脚本动态添加这类script元素,必须设置blocking = "render",它才会阻塞渲染。 crossorigin-
对于未通过标准 CORS 检查的脚本,普通
script元素仅向window.onerror传递最少的信息。若站点的静态媒体使用单独的域名,请使用此属性以允许记录错误。有关其有效参数的更详细说明,请参见 CORS 设置属性。 defer-
设置此布尔属性可向浏览器表明,脚本应在文档解析后、触发
DOMContentLoaded事件前执行。带有
defer属性的脚本会阻止触发DOMContentLoaded事件,直至脚本加载完毕并完成求值。警告:缺少
src属性(即内联脚本)时不得使用此属性;在这种情况下它不起作用。defer属性对模块脚本无效——模块脚本默认延迟执行。带有
defer属性的脚本会按其在文档中出现的顺序执行。此属性可消除阻塞解析器的 JavaScript:浏览器本来必须先加载并对脚本求值,才能继续解析。
async在此情形下有类似作用。若同时指定此属性和
async属性,该元素的行为等同于只指定async属性。 fetchpriority-
提供获取外部脚本时所用相对优先级的提示。允许的值为:
integrity-
此属性包含脚本的一个或多个散列值。它用于确保脚本内容符合开发者预期,且未在供应链攻击中被恶意脚本替换。缺少
src属性时不得指定此属性。另请参阅子资源完整性。 nomodule-
设置此布尔属性可表明脚本不应在支持 ES 模块的浏览器中执行。实际上,可借此为不支持模块化 JavaScript 的旧浏览器提供回退脚本。
nonce-
用于允许 script-src Content-Security-Policy 中脚本的加密一次性随机数(仅使用一次的数值)。服务器每次传输策略时都必须生成唯一的 nonce 值。提供无法猜测的 nonce 至关重要,否则绕过资源策略轻而易举。
referrerpolicy-
指定获取脚本或脚本所获取资源时要发送的 referrer:
no-referrer:不发送Referer标头。no-referrer-when-downgrade:不将Referer标头发送至没有 TLS(HTTPS)的源。origin:发送的 referrer 限于引用页面的源:其协议、主机和端口。origin-when-cross-origin:发送至其他源的 referrer 限于协议、主机和端口。同源导航仍会包含路径。same-origin:向同源请求发送 referrer,但跨源请求不包含 referrer 信息。strict-origin:仅当协议安全级别相同(HTTPS→HTTPS)时,将文档源作为 referrer 发送;不发送至安全性较低的目标(HTTPS→HTTP)。strict-origin-when-cross-origin(默认值):同源请求发送完整 URL;协议安全级别相同(HTTPS→HTTPS)时仅发送源;不向安全性较低的目标(HTTPS→HTTP)发送标头。unsafe-url:referrer 包含源和路径(但不包含片段、密码或用户名)。此值不安全,因为它会将受 TLS 保护资源的源和路径泄露给不安全的源。
备注:空字符串值(
"")既是默认值,也是在不支持referrerpolicy时的回退值。若未在<script>元素上明确指定referrerpolicy,它会采用更高层级的 referrer 策略,即为整个文档或域设置的策略。若没有更高层级的策略,空字符串等同于strict-origin-when-cross-origin。 src-
此属性指定外部脚本的 URI;可作为直接在文档中嵌入脚本的替代方式。
type-
此属性表示脚本的类型。其值为下列之一:
- 属性未设置(默认值)、空字符串或 JavaScript MIME 类型
-
表示脚本是包含 JavaScript 代码的“经典脚本”。若脚本引用 JavaScript 代码,建议作者省略该属性,而非指定 MIME 类型。JavaScript MIME 类型列于 IANA 媒体类型规范。
importmap-
表示元素主体包含导入映射。导入映射是 JSON 对象,开发者可用它控制浏览器导入 JavaScript 模块时如何解析模块说明符。
module-
使代码作为 JavaScript 模块处理。脚本内容的处理会延后。
charset和defer属性无效。关于使用module的信息,请参阅 JavaScript 模块指南。与经典脚本不同,模块脚本跨源获取时必须使用 CORS 协议。 speculationrules-
表示元素主体包含推测规则。推测规则采用 JSON 对象形式,用于确定浏览器应预获取或预渲染哪些资源。这是 推测规则 API 的一部分。
- 任何其他值
-
嵌入内容将作为数据块处理,浏览器不会处理它。开发者必须使用有效的非 JavaScript MIME 类型表示数据块。包括
src属性在内的所有其他属性都会被忽略。
已弃用的属性
备注
没有 async、defer 或 type="module" 属性的脚本,以及没有 type="module" 属性的内联脚本,会在浏览器继续解析页面前立即获取并执行。
脚本应以 text/javascript MIME 类型提供,但浏览器较宽容:只有脚本以图像类型(image/*)、视频类型(video/*)、音频类型(audio/*)或 text/csv 提供时才会阻止它。若脚本被阻止,将向元素发送 error 事件;否则,发送 load 事件。
示例
>基本用法
此示例展示如何使用 <script> 元素导入(外部)脚本:
<script src="javascript.js"></script>
以下示例展示如何在 <script> 元素内放置(内联)脚本:
<script>
alert("你好,世界!");
</script>
async 和 defer
使用 async 属性加载的脚本,在获取脚本时不会阻塞页面下载。然而下载完成后,脚本将执行,从而阻塞页面渲染。这意味着在脚本执行完毕前,网页其余内容无法被处理并显示给用户。无法保证脚本按任何特定顺序运行。当页面中的脚本彼此独立且不依赖页面中其他脚本时,最好使用 async。
使用 defer 属性加载的脚本将按其在页面中出现的顺序加载。它们会等到页面内容全部加载后才运行;若脚本依赖 DOM 已就绪(例如修改页面中的一个或多个元素),这很有用。
下图直观展示不同脚本加载方式及其对页面的影响:

此图来自 HTML 规范,在 CC BY 4.0 许可条款下复制、裁剪为缩小版本。
例如,若有以下脚本元素:
<script async src="js/vendor/jquery.js"></script>
<script async src="js/script2.js"></script>
<script async src="js/script3.js"></script>
不能依赖脚本的加载顺序。jquery.js 可能在 script2.js 和 script3.js 之前或之后加载;若出现这种情况,那些脚本中依赖 jquery 的函数将产生错误,因为脚本运行时 jquery 尚未定义。
当有一批后台脚本需要加载,并且只想让它们尽快到位时,应使用 async。例如,可能有一些游戏数据文件需在游戏真正开始时使用,但目前只想显示游戏介绍、标题和大厅,而不希望它们被脚本加载阻塞。
使用 defer 属性加载的脚本(见下文)将按其在页面中出现的顺序运行,并在脚本和内容下载完毕后执行:
<script defer src="js/vendor/jquery.js"></script>
<script defer src="js/script2.js"></script>
<script defer src="js/script3.js"></script>
在第二个示例中,可以确定 jquery.js 会在 script2.js 和 script3.js 前加载,且 script2.js 会在 script3.js 前加载。它们会等到页面内容全部加载后才运行;若脚本依赖 DOM 已就绪(例如修改页面中的一个或多个元素),这很有用。
总结:
async和defer都会指示浏览器在下载页面其余部分(DOM 等)时,在单独线程中下载脚本,因此获取期间不会阻塞页面加载。- 带有
async属性的脚本会在下载完成后立即执行。这会阻塞页面,且不保证任何特定执行顺序。 - 带有
defer属性的脚本按其在页面中的顺序加载,且仅在一切加载完毕后执行。 - 如果脚本应立即运行且没有依赖项,请使用
async。 - 如果脚本需等待解析并依赖其他脚本和/或 DOM 已就绪,请使用
defer加载,并按希望浏览器执行它们的顺序放置对应的<script>元素。
模块回退
支持 type 属性 module 值的浏览器会忽略带有 nomodule 属性的脚本。因此,可以在使用模块脚本的同时,为不支持它的浏览器提供标有 nomodule 的回退脚本。
<script type="module" src="main.js"></script>
<script nomodule src="fallback.js"></script>
使用导入映射导入模块
在脚本中导入模块时,若不使用 type=importmap 功能,则每个模块必须使用绝对或相对 URL 的模块说明符导入。下例中,第一个模块说明符是绝对 URL,第二个("./shapes/square.js")相对于文档的基 URL 解析。
import { name as circleName } from "https://example.com/shapes/circle.js";
import { name as squareName, draw } from "./shapes/square.js";
导入映射允许提供一个映射;若匹配,则可替换模块说明符中的文本。下方导入映射定义 circle 和 square 键,可作为上方模块说明符的别名。
<script type="importmap">
{
"imports": {
"circle": "https://example.com/shapes/circle.js",
"square": "./shapes/square.js"
}
}
</script>
这样便可使用模块说明符中的名称(而不是绝对或相对 URL)导入模块:
import { name as circleName } from "circle";
import { name as squareName, draw } from "square";
有关导入映射的更多示例,请参阅 JavaScript 模块指南中的使用导入映射导入模块章节。
在 HTML 中嵌入数据
还可通过在 type 属性中指定有效的非 JavaScript MIME 类型,使用 <script> 元素将服务端渲染的数据嵌入 HTML。
<!-- 由服务器生成 -->
<script id="data" type="application/json">
{
"userId": 1234,
"userName": "Maria Cruz",
"memberSince": "2000-01-01T00:00:00.000Z"
}
</script>
<!-- 静态 -->
<script>
const userInfo = JSON.parse(document.getElementById("data").text);
console.log("用户信息:%o", userInfo);
</script>
在脚本获取并执行前阻止渲染
可在 blocking 属性中包含 render 令牌;页面渲染会被阻止,直至脚本被获取并执行。下例阻塞异步脚本的渲染,因此该脚本不会阻塞解析,但保证会在开始渲染前完成求值。
<script blocking="render" async src="async-script.js"></script>
技术概要
规范
| 规范 |
|---|
| HTML> # the-script-element> |