六维教程

JavaScript 引入方式

上一篇 JavaScript 是什么 了解了 JavaScript 的能力,这一篇学习怎么把 JavaScript 代码放进网页。一共有三种方式,行内、内嵌、外部文件,各有适用场景。

行内方式

行内方式是把代码直接写在 HTML 标签的属性里,最常见的是 onclick 属性。

<button onclick="alert('你好')">点我</button>

点击按钮会弹出一个提示框。这种写法简单直接,但基本只在演示里出现,不推荐在真实项目使用。原因包括

  • 代码和结构耦合在一起,HTML 和 JavaScript 混在一处,后期难维护。
  • 难以复用,每个按钮都要写一遍,改动要逐处修改。
  • 无法写稍长一点的逻辑,代码一多就拥挤不堪。

真实项目里,行为应该和结构分离,就像 CSS 不写在标签里一样。

内嵌方式

内嵌方式是用 script 标签把代码写在页面里,通常放在 head 或 body 中。

<!DOCTYPE html>
<html lang="zh-CN">
  <body>
    <script>
      console.log('页面加载了');
    </script>
  </body>
</html>

打开页面后,控制台会输出”页面加载了”。内嵌适合页面独有、量不大的代码,比如页面初始化逻辑。缺点是不能复用,其他页面想用同样代码只能再复制一份。

外部文件方式

外部文件方式把代码写在一个独立的 .js 文件里,再用 script 标签引入。

<script src="app.js"></script>

app.js 内容如下

console.log('来自外部文件的输出');

这是实际项目最推荐的方式,优点包括

  • 可复用。同一个文件可以被多个页面引入。
  • 可缓存。浏览器会把文件缓存下来,页面二次访问不用重新下载。
  • 便于维护。代码集中管理,和 HTML 结构彻底分离。

注意 script 标签引入外部文件时中间不能写代码,写了也会被忽略。

为什么放在 body 结束标签前面

细心的读者会发现,教程示例里 script 都放在 body 结束标签之前,这是有意为之。

浏览器解析 HTML 是自上而下的,遇到 script 标签会停下来,先下载并执行完脚本,再继续解析后面的结构。如果脚本放在 head 里且执行耗时,用户会看到页面长时间空白。

把 script 放在 body 结束标签前,页面结构已经解析完,脚本执行时页面已经渲染出来了,用户感知的加载速度更快。这是最稳妥的传统做法。

defer 和 async 简介

除了调整位置,现代写法还有两个属性可以控制外部脚本的加载时机,defer 和 async。它们都是异步加载方式,意思是下载脚本不阻塞 HTML 解析,区别在执行时机。

<script src="app.js" defer></script>
<script src="app2.js" async></script>
  • defer 表示等文档解析完成后执行,多个 defer 脚本保持声明顺序。
  • async 表示下载完立即执行,不保证顺序,也不等文档解析完成。

两者都不适用于内嵌脚本,只对外部文件生效。新手阶段记住 defer 更常用、行为更可预期就够了,具体取舍后面遇到再深入。

完整示例

综合练习一下,写一个完整页面,包含按钮、内嵌脚本和外部文件。文件结构如下

study/
  index.html
  app.js

index.html 内容

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8">
    <title>JS 引入方式示例</title>
  </head>
  <body>
    <h1>JavaScript 引入方式</h1>
    <button id="btn">点我</button>
    <script>
      const message = '内嵌脚本输出的信息';
      console.log(message);
    </script>
    <script src="app.js"></script>
  </body>
</html>

app.js 内容

console.log('外部脚本输出的信息');

在浏览器打开 index.html,按 F12 打开控制台,会依次看到两行输出,一行来自内嵌脚本,一行来自外部文件。页面先渲染出标题和按钮,再执行脚本,顺序符合预期。

小结

  • 三种引入方式包括行内、内嵌、外部文件,外部文件最推荐。
  • 行内写在标签属性里,代码和结构耦合,不推荐。
  • script 放 body 结束标签前,是因为脚本执行会阻塞 HTML 解析,先把页面结构渲染出来。
  • defer 等文档解析完成后执行且保持顺序,async 下载完立即执行,都只对外部脚本有效。
  • 完整页面示例演示了内嵌脚本和外部文件同时工作的写法。
上一篇
JavaScript 是什么
下一篇
JavaScript 基本语法与注释