脚本标签
脚本标签
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-Type
h 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>
我还没有看到有人用了它,然而如果你知道有哪个网站用了,可以在下面评论。