2HTML 中的 JavaScript
标签位置
过去,所有<script>
元素都被放在页面的<head>
标签内,如下面的例子所示:
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script src="example1.js"></script>
<script src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
这种做法的主要目的是把外部的 CSS 和 JavaScript 文件都集中放到一起。不过,把所有 JavaScript 文件都放在<head>
里,也就意味着必须把所有 JavaScript 代码都下载、解析和解释完成后,才能开始渲染页面(页面在浏览器解析到<body>
的起始标签时开始渲染)。
对于需要很多 JavaScript 的页面,这会导致页面渲染的明显延迟,在此期间浏览器窗口完全空白。为解决这个问题,现代 Web 应用程序通常将所有 JavaScript 引用放在<body>
元素中的页面内容后面,如下面的例子所示:
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
</head>
<body>
<!-- 这里是页面内容 -->
<script src="example1.js"></script>
<script src="example2.js"></script>
</body>
</html>
这样一来,页面会在处理 JavaScript 代码之前完全渲染页面。用户会感觉页面加载更快了,因为浏 览器显示空白页面的时间短了。
动态加载脚本
除了<script>
标签,还有其他方式可以加载脚本。因为 JavaScript 可以使用 DOM API,所以通过
向 DOM 中动态添加 script 元素同样可以加载指定的脚本。只要创建一个 script 元素并将其添加到
DOM 即可。
let script = document.createElement("script");
script.src = "gibberish.js";
document.head.appendChild(script);
当然,在把 HTMLElement 元素添加到 DOM 且执行到这段代码之前不会发送请求。
<script>
标签有下列常见属性
async
async 表示立即下载脚本,不妨碍页面的其他操作(异步下载)
- 无法保证每个 js 的顺序
- 用于互不依赖的 js
- 主要目的是不让页面等 js
async 脚本保证会在页面的 load 事件前执行,但可能会在 DOMContentLoaded 之前或之后,正因为如此,异步脚本不应该在加载期间修改 DOM。
使用 async 也会告诉页面你不会使用 document.write,不过好的 Web 开发实践根本就不推荐使用这个方法。
defer
defer 延迟到文档完全解析和显示之后在执行
- 在
</html>
标签之后执行
src 外部文件链接
type
type 表示编写代码使用的脚本语言的内容类型 text/javascript
小结
JavaScript 是通过<script>
元素插入到 HTML 页面中的。这个元素可用于把 JavaScript 代码嵌入到 HTML 页面中,跟其他标记混合在一起,也可用于引入保存在外部文件中的 JavaScript。本章的重点可以总结如下。
- 要包含外部 JavaScript 文件,必须将 src 属性设置为要包含文件的 URL。文件可以跟网页在同一台服务器上,也可以位于完全不同的域。
- 所有
<script>
元素会依照它们在网页中出现的次序被解释。在不使用 defer 和 async 属性的情况下,包含在<script>
元素中的代码必须严格按次序解释。 - 对不推迟执行的脚本,浏览器必须解释完位于
<script>
元素中的代码,然后才能继续渲染页面的剩余部分。为此,通常应该把<script>
元素放到页面末尾,介于主内容之后及</body>
标签之前。 - 可以使用 defer 属性把脚本推迟到文档渲染完毕后再执行。推迟的脚本原则上按照它们被列出的次序执行。
- 可以使用 async 属性表示脚本不需要等待其他脚本,同时也不阻塞文档渲染,即异步加载。异步脚本不能保证按照它们在页面中出现的次序执行。
- 通过使用
<noscript>
元素,可以指定在浏览器不支持脚本时显示的内容。如果浏览器支持并启用脚本,则<noscript>
元素中的任何内容都不会被渲染。