脚本标签

脚本标签

script 标签是用来指定在网页上执行哪个 JavaScript 的。Script 标签可以直接包含 JavaScript 代码,或者指向一个 JavaScript 外链 URL。

脚本的执行顺序

默认执行顺序

下面的代码很直观地说明了这一点:

<script>
  var x = 3;
</script>
<script>
  alert(x);
  // Will alert "3";
</script>

使用外链资源时加载次序没有那么直观,但依然是成立的:

<script src="//typekit.com/fj3j1j2.js"></script>
<!-- This second script won’t execute until typekit has executed, or timed out -->
<script src="//my.site/script.js"></script>

如果你混合使用外链和内联的 JavaScript,这个规则同样适用。这意味着如果你的网站有很慢的脚本在页面较前部分被加载,你的网页加载就会被显著拖慢。这也意味着后加载的脚本可以依赖先加载的脚本。页面元素在它之前的所有脚本都加载完毕之前是不会执行渲染的。这意味着你可以你可以在页面加载之前在网页上做各种疯狂的事情,当然前提是你不在意因此而造成的性能问题。然而这个规则不适用于你在网页加载完成之后通过 document.appendChild之类的方法添加 script 标签到 DOM 中。这些标签会根据浏览器请求处理完成的先后执行脚本,不再保证加载顺序。 当一个 script 标签被执行,在它之前的 HTML 元素可以访问(但是在它之后的还不能用):

<html>
  <head>
    <script>
      // document.head is available
      // document.body is not!
    </script>
  </head>
  <body>
    <script>
      // document.head is available
      // document.body is available
    </script>
  </body>
</html>

你可以想象 HTML 解析器一个标签一个标签地访问文档,当它解析到 script 标签时,马上执行其中的 JavaScript。这意味着只有当开始标签出现在当前脚本之前的 DOM 节点才可以在当前 JavaScript 中被访问(通过 querySelectorALl,jQuery 等等)。一个有用的推论是 document.head在任何写在网页上的 JavaScript 几乎总是可用。document.body只有当你将 script 标签写在 ``标签中或者它之后的时候才可用。

async 和 defer

HTML5 添加了两个工具来控制脚本的执行。

  • async表示“不用马上执行它”。更具体地它表示:我不介意你在整个网页加载完成之后执行这个脚本,把它放在其他脚本执行之后。这对于统计分析脚本来说非常有用,因为页面上没有其他的代码需要依赖于统计脚本执行。定义一个页面需要的变量或函数在 async的代码中是不行的,因为你没有方法知道什么时候 async代码将会被实际执行。

  • defer表示“等待页面解析完成之后执行”。它大致等价于将你的脚本绑定到 DOMContentedLoaded事件,或者使用 jQuery.ready。当这个代码被执行,DOM 中的一切元素都可用。不同于 async,所有加了 defer的脚本将会按照它们出现在 HTML 页面中的顺序执行,它只是推迟到 HTML 页面解析完毕后开始执行。

type: 自定义脚本类型

从历史上看(自 Netsacpe 2 诞生起),在 script 标签上是否写上 type=text/javascript没有什么关系。如果你通过 type设置一个非 JavaScript 的 MIME 类型,浏览器不会执行它。当你想要定义你自己的语言时,这会很酷:

<script type="text/emerald">
  make a social network
    but for cats
</script>

这段代码实际执行结果由你自己决定,例如:

<script>
  var codez = document.querySelectorAll("script[type="text/emerald"]");
  for (var i=0; i < codez.length; i++)
    runEmeraldCode(codez[i].innerHTML);
</script>

定义 runEmeraldCode 函数留给你们作为练习。如果你有特别的需要,你也可以重写页面上 script 标签的默认 type,方法是通过一个 meta标签:

<meta http-equiv="Content-Script-Type" content="text/vbscript" />

或者一个请求返回一个 Content-Script-Typeh eader。可以读一下 Web 上奇怪的脚本语言的一个简短历史这篇文章有关于 type用法的更详细信息。

integrity

integrity属性是子资源完整性新规范的一部分。它允许你为脚本文件将包含的内容内容提供一个 hash。这意味着可以防止在传输的时候内容丢失或者被恶意修改。就算使用了 SSL,这个规范也是有意义的,因为有时候你要加载的资源是你无法控制的站外资源,比如 code.jquery.com。如果你选择使用它,你要在 script 标签里包含一个 hash 类型以及 hash 值,将它们以连字符隔开。看起来类似下面这样:

<script
  src="//code.jquery.com/jquery.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
></script>

我还没有看到有人用了它,然而如果你知道有哪个网站用了,可以在下面评论。

上一页
下一页