谈谈 <script> 标签以及其加载顺序问题,包含 defer & async

<script>标签出现的很早,其作用:引入 JavaScrit 代码。这个元素是由 Netscape 创造,并在 Netscape Navigator 2中首先实现。后来,这个元素被加入到正式的 HTML 规范中。属性包括:

  • async:可选,表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本。只对外部脚本文件有效。
  • charset:可选。表示通过 src 属性指定的代码的字符集。由于大多数浏览器会忽略它的值,因此这个属性很少有人用。
  • defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。IE7 及更早版本对嵌入脚本也支持这个属性。
  • language: 已废弃。原来用于表示编写代码使用的脚本语言(如 JavaScript 、 JavaScript1.2 或 VBScript )。大多数浏览器会忽略这个属性,因此也没有必要再用了。
  • src:可选。表示包含要执行代码的外部文件。
  • type:可选。可以看成是 language 的替代属性;表示编写代码使用的脚本语言的内容类型(也称为 MIME 类型)。虽然 text/javascript
  • 和 text/ecmascript 都已经不被推荐使用,但人们一直以来使用的都还是 text/javascript 。实际上,服务器在传送 JavaScript 文件时使用的
  • MIME 类型通常是 application/x–javascript ,但在 type 中设置这个值却可能导致脚本被忽略。另外,在非IE浏览器中还可以使用以下值:
  • application/javascript 和 application/ecmascript 。考虑到约定俗成和最大限度的浏览器兼容性,目前 type 属性的值依旧还是
  • text/javascript 。不过,这个属性并不是必需的,如果没有指定这个属性,则其默认值仍为text/javascript 。

说明:在以上属性中 async属性是 HTML5 中的新属性。

1、引入方式 JavaScript 的两种方式:

  1. 内联形式:这种方式指的是在 html 文件中,添加一个<script></scritp>标签,然后将 JavaScript代码直接写在里面。
  2. 外置形式:外置形式是将 JavaScript 代码写在外部的一个文件里面,在 html 文件中通过 <script> 标签的 src 属性引入。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>script 标签</title>
  <!--内联-->
  <script type="text/javascript">
    console.log('内联 JavaScript');
  </script>
</head>

<body>
  <!-- content -->
  <!-- 外置方式 -->
  <script type="text/javascript" src="./js/01.js"></script>
</body>
</html>

两种引入形式的比较(毫无疑问,外置形式明显好于内联形式)主要表现为以下方面:

  • 可维护性:外置 Javascript 文件可以被多个页面调用而不用在每个页面上反复地书写.如果有需要改变的部分,你只需要在一处修改即可.所以外置JavaScript 导致代码工作量减少,进而使得维护手续也更加方便。
  • 可缓存:浏览器能够根据具体的设置缓存链接的所有外部 JavaScript文件。也就是说,如果有两个页面都使用同一个文件,那么这个文件只需下载一次。因此,最终结果就是能够加快页面加载的速度。
  • 关注点分离:将 JavaScript 封装在外部的.js文件遵循了关注点分离的法则.总体来说,分离 HTML,CSS 和 JavaScript 从而让我们更容易操纵他们.而且如果是多名开发者同步工作的话,这样也更方便。

因此,在今后的开发中尽量使用外置方式的形式引入JavaScript。

2、<script> 标签加载顺序

2.1)script标签位置:

<script> 标签加载顺序,和标签的位置有关,<script> 标签的位置有两种:

  1. 放在<head>元素里面:这是比较传统的做法,目的就是把所有外部文件(包括 CSS 文件和 JavaScript 文件)的引用都放在相同的地方。可是,在<head> 元素中包含所有 JavaScript 文件,意味着必须等到全部 JavaScript 代码都被下载、解析和执行完成以后,才能开始呈现页面的内容(浏览器在遇到 <body> 标签时才开始呈现内容),可能会影响体验;
  2. 放在<body> 元素中:在解析包含的 JavaScript 代码之前,页面的内容将完全呈现在浏览器中。而用户也会因为浏览器窗口显示空白页面的时间缩短而感到打开页面的速度加快了

所以,我们建议放到body中。例如:

<!DOCTYPE html>
<html>

<head>
  <title>Example HTML Page</title>
</head>

<body>
  <!-- 这里放内容 -->
  <script type="text/javascript" src="example1.js"></script>
  <script type="text/javascript" src="example2.js"></script>
</body>

</html>

2.2)延迟加载:

HTML 4.01 为 <script> 标签定义了 defer 属性。这个属性的用途是表明脚本在执行时不会影响页面的构造。也就是说,脚本会被延迟到整个页面都解析完毕后再运行。因此,在 <script> 元素中设置defer 属性,相当于告诉浏览器立即下载,但延迟执行,比如:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>script 标签</title>
  <script defer="defer" type="text/javascript" src="./js/01.js"></script>
  <script defer="defer" type="text/javascript" src="./js/02.js"></script>
</head>

<body>
  <!-- content -->
  <script type="text/javascript" src="./js/03.js"></script>
</body>

</html>

在这个例子中,虽然我们把 <script> 元素放在了文档的 <head> 元素中,但其中包含的脚本将延迟到浏览器遇到 </html>标签后再执行。HTML5 规范要求脚本按照它们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于 DOMContentLoaded 事件执行。在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在 DOMContentLoaded 事件触发前执行,因此最好只包含一个延迟脚本。(因为不同浏览器不一定都是按照HTML5规范执行的)

2.3)异步加载
HTML5 为 <script> 元素定义了 async 属性。这个属性与 defer 属性类似,都用于改变处理脚本的行为。同样与 defer 类似, async 只适用于外部脚本文件,并告诉浏览器立即下载文件,下载完成后立即执行。但与 defer不同的是,标记为 async 的脚本并不保证按照指定它们的先后顺序执行。例如:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>script 标签</title>
  <script async type="text/javascript" src="./js/01.js"></script>
  <script async type="text/javascript" src="./js/02.js"></script>
</head>

<body>
  <!-- content -->
</body>

</html>

在以上代码中,可能由于 01.js 下载时间比较长,由于两个 <script> 标签都是异步执行,互不干扰,因此 02.js 可能就会先于 01.js 执行。因此,确保两者之间互不依赖非常重要。指定 async 属性的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容。为此,建议异步脚本不要在加载期间修改 DOM。

下面将用一张图来描述<script> 标签三种状态下(normal,defer,async)于html加载的关系:

图片描述

猜你喜欢

转载自blog.csdn.net/liuxiao723846/article/details/119653368