此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。

View in English Always switch to English

<script> HTML 脚本元素

基线
广泛可用
*

自 2015年7月 起,此特性已在主流浏览器中得到支持,可在大多数设备和浏览器版本中正常使用。

* 此特性的某些部分的支持程度可能有所不同。

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

提供获取外部脚本时所用相对优先级的提示。允许的值为:

high

相较于其他外部脚本,以高优先级获取该外部脚本。

low

相较于其他外部脚本,以低优先级获取该外部脚本。

auto

不设置获取优先级偏好。这是默认值。未设置或设置无效值时使用。

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 属性在内的所有其他属性都会被忽略。

已弃用的属性

charset

若存在,其值必须与 utf-8 进行 ASCII 大小写不敏感匹配。无需指定 charset 属性,因为文档必须使用 UTF-8,script 元素会从文档继承字符编码。

language

与 type 属性类似,此属性标识所用的脚本语言。但与 type 属性不同,它的可能值从未标准化。应改用 type 属性。

备注

没有 async、defer 或 type="module" 属性的脚本,以及没有 type="module" 属性的内联脚本,会在浏览器继续解析页面前立即获取并执行。

脚本应以 text/javascript MIME 类型提供,但浏览器较宽容:只有脚本以图像类型(image/*)、视频类型(video/*)、音频类型(audio/*)或 text/csv 提供时才会阻止它。若脚本被阻止,将向元素发送 error 事件;否则,发送 load 事件。

示例

基本用法

此示例展示如何使用 <script> 元素导入(外部)脚本:

html
<script src="javascript.js"></script>

以下示例展示如何在 <script> 元素内放置(内联)脚本:

html
<script>
  alert("你好,世界!");
</script>

async 和 defer

使用 async 属性加载的脚本,在获取脚本时不会阻塞页面下载。然而下载完成后,脚本将执行,从而阻塞页面渲染。这意味着在脚本执行完毕前,网页其余内容无法被处理并显示给用户。无法保证脚本按任何特定顺序运行。当页面中的脚本彼此独立且不依赖页面中其他脚本时,最好使用 async。

使用 defer 属性加载的脚本将按其在页面中出现的顺序加载。它们会等到页面内容全部加载后才运行;若脚本依赖 DOM 已就绪(例如修改页面中的一个或多个元素),这很有用。

下图直观展示不同脚本加载方式及其对页面的影响:

三种脚本加载方式的工作原理:默认方式会在获取和执行 JavaScript 时阻塞解析。使用 async 时,解析仅在执行期间暂停。使用 defer 时,解析不会暂停,但会在其他所有内容解析后才执行。

此图来自 HTML 规范,在 CC BY 4.0 许可条款下复制、裁剪为缩小版本。

例如,若有以下脚本元素:

html
<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 属性加载的脚本(见下文)将按其在页面中出现的顺序运行,并在脚本和内容下载完毕后执行:

html
<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 的回退脚本。

html
<script type="module" src="main.js"></script>
<script nomodule src="fallback.js"></script>

使用导入映射导入模块

在脚本中导入模块时,若不使用 type=importmap 功能,则每个模块必须使用绝对或相对 URL 的模块说明符导入。下例中,第一个模块说明符是绝对 URL,第二个("./shapes/square.js")相对于文档的基 URL 解析。

js
import { name as circleName } from "https://example.com/shapes/circle.js";
import { name as squareName, draw } from "./shapes/square.js";

导入映射允许提供一个映射;若匹配,则可替换模块说明符中的文本。下方导入映射定义 circle 和 square 键,可作为上方模块说明符的别名。

html
<script type="importmap">
  {
    "imports": {
      "circle": "https://example.com/shapes/circle.js",
      "square": "./shapes/square.js"
    }
  }
</script>

这样便可使用模块说明符中的名称(而不是绝对或相对 URL)导入模块:

js
import { name as circleName } from "circle";
import { name as squareName, draw } from "square";

有关导入映射的更多示例,请参阅 JavaScript 模块指南中的使用导入映射导入模块章节。

在 HTML 中嵌入数据

还可通过在 type 属性中指定有效的非 JavaScript MIME 类型,使用 <script> 元素将服务端渲染的数据嵌入 HTML。

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 令牌;页面渲染会被阻止,直至脚本被获取并执行。下例阻塞异步脚本的渲染,因此该脚本不会阻塞解析,但保证会在开始渲染前完成求值。

html
<script blocking="render" async src="async-script.js"></script>

技术概要

内容分类 元数据内容、流式内容、短语内容。
允许的内容 动态脚本,例如 text/javascript。
标签省略 不允许;开始和结束标签均为必需。
允许的父元素 接受元数据内容或短语内容的任何元素。
隐含的 ARIA 角色 没有对应的角色
允许的 ARIA 角色 没有允许的 role
DOM 接口 HTMLScriptElement

规范

规范
HTML
# the-script-element

浏览器兼容性

参见