<script>标签的async和defer属性的使用

254 阅读4分钟

前言

近期在拜读了《JavaScript 高级程序设计》第四版 一书,以巩固自己的基础为目标阅读。为了更好的学习总结,笔者会连续输出章节的学习内容与总结,感兴趣的话,可以期待一下 -.-。笔者文笔简陋,若有表述不正确的地方,还请留言指出,大家共同进步。

<script> 的使用

  1. 嵌入行内Javascript ;代码放在<script>元素中就行
<script>
    console.log('Hello World!')
</script>

使用行内Javascript代码时,代码中不能出现</script>,浏览器解析行内脚本的时候会将其当成结束标签</script>。可以使用转义符解决这个问题 <\/script>

<script>
    console.log('<\/script>')
</script>
  1. 设置src属性,引入外部脚本
<script src="myscripts.js"></script>

使用src属性的</script>内部不应该在包含其他的行内脚本,因为浏览器会忽略行内代码。

<script>可以解析来自外域的js文件,src属性可以设置为一个完整的URL,而且这个URL指向的资源可以和当前HTML页面不在同一个域中。不受同源策略限制,但返回并被执行的脚本收限制。

引用外部域的代码注意

  • 引用外部域的脚本文件,小心恶意的程序员随之可能替换这个文件。
  • 最好引用的外部域是自己所有,或者是一个可信的来源
  • <script>integrity属性就可以防范这个问题,但是需要考虑这个属性的兼容性。

<script> 的标签属性

<script> 一共有8个属性。

  • async 异步执行脚本(仅适用于外部脚本)
  • charset 外部脚本文件中使用的字符编码。
  • crossorigin 配置相关请求的CORS(跨资源共享)设置。默认不使用CORScrossorigin="anonymous"配置文件请求不必设置凭据标志。crossorigin="use-credentials"设置凭据标志,意味着出站请求会包含凭据。
  • defer 是否延迟执行脚本。
  • integrity 允许对比接收到的资源和指定的加密签名以验证子资源完整性。如果接收到的资源的签名与这个属性指定的签名不匹配,则页面会报错,脚本不会执行。这个属性用于确保内容分发网络(CDN)不会提供恶意内容。
  • language (废弃),规定代码中的脚本语言,大部分浏览器都会忽略这个属性,不应该在使用它。
  • src 外部脚本文件的URL
  • type 代替 language,表示代码块中脚本语言的内容类型,按照惯例这个值始终都是"text/javascript",尽管"text/javascript""text/ecmascript"都已经废弃了。

1. async 属性(异步执行脚本)

表示脚本将被异步执行(只对外部脚本文件有效,也就是使用src属性的时候)。 设置 async 属性的目的就是告诉浏览器,不必等脚本下载和执行完成后再加载页面,同样也不必等到该异步脚本下载和执行后再加载其他脚本。

语法

<script async="async">

特点:

  • 该属性只对外部脚本有效
  • 异步脚本不应该在加载期间修改DOM,此时页面可能还没有加载完成 兼容性 Firefox3.6,Safari 5和Chrome 7及以后

2. defer 属性(推迟执行脚本)

设置该属性,表示脚本在执行的时候不会改变文档内容。因此该脚本可以在正个页面解析完之后在执行。

设置该属性会告诉浏览器立即下载脚本,但是推迟执行脚本,直到页面加载为止。

语法

<script async="async">

特点:

  • 只对外部脚本有效
  • 设置defer属性的多个<script>标签会按照它们出现的顺序执行。不过,实际由于事件的执行机制,推迟执行的脚本不一定总是按顺序执行,所以最好只包含一个推迟执行脚本。
  • 该属性的兼容性不是很好,建议将推迟执行脚本放在页面底部。 兼容性 IE4,Firefox3.5,Safari和Chrome 7及以后

3. 动态加载脚本

动态生成<script>标签,添加到页面中。

let script = document.createElement("script");
script.src = "myscripts.js";
document.head.appendChild(script);

用上面这种方式创建的<script>,是以异步的方式加载的,相当于添加了async属性。由于不是所有的浏览器都支持async属性,因此要统一动态脚本的加载行为,可以明确设为同步加载:

let script = document.createElement("script");
script.src = "myscripts.js";
script.async = false; // (*)
document.head.appendChild(script);

这种方式获取的资源浏览器预加载是不可见的,要想让预加载器知道这些动态请求文件的存在,可以在文档头部显示声明:

<link rel="preload" href="myscripts.js">

--end--