<script>：脚本元素
=============

HTML **`<script>`** 元素用于嵌入可执行代码或数据，这通常用作嵌入或者引用 JavaScript 代码。`<script>` 元素也能在其他语言中使用，比如 WebGL 的 GLSL 着色器语言和 JSON。

|  |  |
| --- | --- |
| 内容分类 | 元数据内容、流式内容、短语内容。 |
| 允许的内容 | 动态脚本，如 `text/javascript`。 |
| 标签省略 | 不允许，开始标签和结束标签都不能省略。 |
| 允许的父元素 | 任何可以接受元数据内容，或者短语内容的元素。 |
| 隐含的 ARIA 角色 | 没有对应的角色 |
| 允许的 ARIA 角色 | 不允许任何 `role` |
| DOM 接口 | `HTMLScriptElement` |

属性
--

该元素包含全局属性。

`async`

对于普通脚本，如果存在 `async` 属性，那么普通脚本会被并行请求，并尽快解析和执行。

对于模块脚本，如果存在 `async` 属性，那么脚本及其所有依赖都会在延缓队列中执行，因此它们会被并行请求，并尽快解析和执行。

该属性能够消除**解析阻塞的 Javascript**。解析阻塞的 Javascript 会导致浏览器必须加载并且执行脚本，之后才能继续解析。`defer` 在这一点上也有类似的作用。

这是个布尔属性：布尔属性的存在意味着 true 值，布尔属性的缺失意味着 false 值。

关于浏览器支持，请参见浏览器兼容性章节。另可参见 asm.js 的异步脚本文章。

`crossorigin`

正常的 `script` 元素将最小的信息传递给 `window.onerror`，用于那些没有通过标准 CORS 检查的脚本。要允许对静态媒体使用独立域名的网站进行错误记录，请使用此属性。参见 CORS 设置属性，以获得对其有效参数的更多描述性解释。

`defer`

这个布尔属性的设置是为了向浏览器表明，该脚本是要在文档被解析后，但在触发 `DOMContentLoaded` 事件之前执行的。

包含 `defer` 属性的脚本将阻塞 `DOMContentLoaded` 事件触发，直到脚本完成加载并执行。

**警告：** 本属性不应在缺少 `src` 属性的情况下使用（也就是内联脚本的情况下），这种情况下将不会生效。

`defer` 属性对模块脚本也不会生效——它们默认是 defer 的。

包含 `defer` 属性的脚本会按照它们出现在文档中的顺序执行。

这个属性能够消除**阻塞解析的 JavaScript**，在这种情况下，浏览器必须在继续解析之前加载和执行脚本。`async` 在这种情况下也有类似的效果。

`fetchpriority` 
实验性

提供一个指示，说明在获取外部脚本时要使用的相对优先级。允许的值：

`high`

获取该脚本的优先级比其他外部脚本的等级要高。

`low`

获取该脚本的优先级比其他外部脚本的等级要低。

`auto`

默认值：自动确定获取该脚本的相对优先级。


`integrity`

包含用户代理可用于验证所获取到资源的完整性的内联元数据。参见子资源完整性。

`nomodule`

这个布尔属性被设置来标明这个脚本不应该在支持 ES 模块的浏览器中执行。实际上，这可用于在不支持模块化 JavaScript 的旧浏览器中提供回退脚本。

`nonce`

在 script-src Content-Security-Policy (en-US) 中允许脚本的一个一次性加密随机数（nonce）。服务器每次传输策略时都必须生成一个唯一的 nonce 值。提供一个无法猜测的 nonce 是至关重要的，因为绕过一个资源的策略是微不足道的。

`referrerpolicy`

表示在获取脚本或脚本获取资源时，要发送哪个 referrer：

* `no-referrer`：不会发送 `Referer` 标头。
* `no-referrer-when-downgrade`（默认）：如果没有 TLS（HTTPS）协议，`Referer` 标头将不会被发送到源上。
* `origin`：发送的 referrer 将被限制在 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 策略，即对整个文档或域设置的策略。如果没有更高级别的策略，空字符串将被视为等同于 `no-referrer-when-downgrade`。

`src`

这个属性定义引用外部脚本的 URI，这可以用来代替直接在文档中嵌入脚本。

**`type`** (en-US)

该属性表示所代表的脚本类型。该属性的值可能为以下类型：

**属性未设置（默认），一个空字符串，或一个 JavaScript MIME 类型**

代表脚本为包含 JavaScript 代码的“传统的脚本”。如果脚本指的是 JavaScript 代码，我们鼓励作者省略这个属性，而不是指定一个 MIME 类型。所有的 JavaScript MIME 类型都列在 IANA 的媒体类型规范中。

`module`

此值导致代码被视为 JavaScript 模块。其中的代码内容会延后处理。`charset` 和 `defer` 属性不会生效。对于使用 `module` 的更多信息，请参见 JavaScript 模块指南。与传统代码不同的是，模块代码需要使用 CORS 协议来跨源获取。

`importmap`

此值代表元素体内包含导入映射（importmap）表。导入映射表是一个 JSON 对象，开发者可以用它来控制浏览器在导入 JavaScript 模块时如何解析模块标识符。

**任何其他值**

所嵌入的内容被视为一个数据块，不会被浏览器处理。开发人员必须使用有效的 MIME 类型，但不是 JavaScript MIME 类型来表示数据块。所有其他属性，包括 `src` 均会被忽略。


`blocking` 
实验性

这个属性明确指出，在获取脚本的过程中，某些操作应该被阻断。要阻断的操作必须是一个以空格分隔的列表，下面列出了阻断属性。

* `render`：屏幕上渲染内容的操作应该被阻断。

### 废弃的属性

`charset` 
已弃用

如果存在，它的值必须是 ASCII 大小写不敏感的“`utf-8`”的匹配。没有必要指定 `charset` 属性，因为文档必须使用 UTF-8，而且 `script` 元素从文档继承其字符编码。

`language` 
已弃用

非标准

和 `type` 属性类似，这个属性定义脚本使用的语言。但是与 `type` 不同的是，这个属性的可能值从未被标准化过。请用 `type` 属性代替这个属性。

备注
--

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

脚本应该以 `text/javascript` 的 MIME 类型提供，但浏览器比较宽容，只有在脚本以图像类型（`image/*`）、视频类型（`video/*`）、音频类型（`audio/*`）或 `text/csv` 提供时才会阻止它们。如果脚本受阻，将向该元素发送 `error` 事件；否则，将发送 `load` (en-US) 事件。

示例
--

### 基本用法

下面这些示例说明了如何使用 `<script>` 元素来导入（外部）脚本。


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


以下示例展示了如何向 `<script>` 元素内放入（内联）脚本。


```html
<script>
 alert("Hello World!");
</script>
```

### 模块回落

支持 `module` 作为 `type` 属性的浏览器忽略任何具有 `nomodule` 属性的脚本。这种机制可以允许你在使用模块脚本时为不支持的浏览器提供 `nomodule` 标记的回落脚本。


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

### 使用导入映射导入模块

在脚本中导入模块时，如果你不使用 `type=importmap` 特性，那么每个模块都必须使用模块指定符来导入，该指定符可以是绝对的也可以是相对的 URL。在下面的例子中，第一个模块标识符（“./shapes/square.js”）是相对于文档的根 URL 解析的，而第二个是绝对 URL。


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


导入映射允许你提供一个映射，当匹配的时候，可以替换模块标识符文本。下面的导入映射定义了“square”和“circle”键，可以作为上述模块指定的别名。


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


这允许我们使用模块标识符中的名称导入模块（而不是绝对或相对的 URL）。


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


关于使用导入映射的更多例子，请参见 JavaScript 模块指南中的使用导入映射导入模块章节。

### 在 HTML 中嵌入数据

你也可以使用 `<script>` 元素来在 HTML 中嵌入服务端渲染的数据，在 `type` 属性中指定一个合法的非 JavaScript MIME 类型即可。


```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("User information: %o", userInfo);
</script>
```

### 在脚本被获取和执行之前阻止渲染

你可以在 `blocking` 属性中包含 `render` 标记；页面的渲染将被阻止，直到脚本被获取和执行。在下面的例子中，我们封锁了一个异步脚本的渲染、这样，脚本不会阻塞解析，但保证在渲染开始前被执行。


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

规范
--

| Specification |
| --- |
| HTML Standard # the-script-element |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `document.currentScript`
* Flavio Copes 关于“高效加载 JavaScript”的文章，解释了 `async` 和 `defer` 之间的区别
* JavaScript 模块指南