javascript 引用资源 & 属性

150 阅读5分钟

javascript(js) 引入到 html 中,可以让 js 更高效的去使用 BOM、DOM 中的能力,需要注意的点是 js 的下载 和执行 并不一定是同步的,下载指的是下载 js 资源。执行可能有延迟性

script 标签及其属性

将 js 插入 html 的主要方法是使用 script 标签

script 标签使用

// 可能在 head 里,也可能在 body 中,取决于具体场景
<script>
  // 你可以叫它 嵌入行内式
  const jsOperation = "这里是js定义的变量";
  // other opreation
</script>
// src 指的是外部的 outer.js 文件资源,外链式
<script src="./outerjs.js"></script>

script 标签的属性

script 标签的属性都是可选的。

  • src 指定外部脚本文件,即要执行的代码外部文件,src 可以是外部域
  • async 表示应该立即开始下载的脚本,但是不能阻止其他页面操作,只对外部脚本文件有效
  • charset 使用 src 属性指定的代码字符集。
  • crossorigin 配置相关的 CORS(跨源资源共享)设置,默认不使用 cors。
    • crosssorigin="anonymous" 配置文件请求不必设置凭据标志。
    • crossorigin="use-credentials" 设置凭据标志,意味着出站请求会包含凭据
  • defer 表示脚本可以延迟到文档完全被解析和显示之后再执行,只对外部脚本文件有效
  • integrity 允许比对接收到的志愿和指定的加密签名以验证子资源完整性(SRI,Subersource Integrity)。如果接收到的资源的签名与这个属性指定的标签名不匹配,则页面会报错,脚本也不执行。这个属性可以用于确保内容分发网络不会提供恶意的内容
  • type 指定内容类型(MIME类型),默认这个值是 "text/javascript",js 文件的 MIME 类型通常是 "application/javascript", 给 type 属性指定值可能导致脚本被忽略。如果这个值 是 module,则代码会被当作 ES6 模块,而且只有这时候代码中才能出现 import 和 export 关键字

注意⚠️: 外部 js 文件的扩展名可以不是 .js,刘安琪不会检查所包含 js 文件的扩展名,这就为使用服务器端脚本语言动态生成 js 代码或者 在浏览器中将 js 扩展语言(如 Typescript or JSX) 转义为 js 提供了可能。服务器经常会根据文件扩展来确定相应的正确 MIME 类型,需要确保服务器能返回正确的 MIME 类型

script 解析和注意事项

src 和 行内 js 代码都存在的情况

建议不要混用,如果 src 和行内 js 都提供了,浏览器会下载并执行脚本文件

<script src="https://www.xxx.com/name.js"></script>
  • 浏览器在解析这个资源时,会向 src 属性指定的路径发送一个 GET 请求取得相应资源,这个初始的请求不受浏览器同源策略限制,但是返回并执行的 js 则受父页面 HTTP/HTTPS 协议的限制
  • 来自外部域的代码会被当成加载它的页面的一部分来加载和解释,可以通过不同域名分发 js。在引用别人服务器上的 js 文件要小心!!integrity 属性是防范这种问题的手段,但这个属性不是所有的浏览器都支持
  • 如果 script 没有 defer 和 async 属性,则浏览器会根据 script 在页面中的出现顺序来依次解释他们。

script 位置

放在 head 中

 <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script defer src="js1.js"></script>
    <script src="js2.js"></script>
  </head>

放在 head 标签内意味着把所有 js 代码都下载、解析和解释完成后,才能开始渲染页面(页面在浏览器解析到 body 的开始标签时开始渲染页面),对于需要很多 js 的页面,都放在 head 中会导致页面渲染明显延迟(可能会出现空白页面),因此解决方案就是将 script 标签放到 靠近 body 的结尾标签位置(这样 js 代码之前就先渲染页面)

推迟执行脚本 defer

  • defer 属性让 script 被延迟到整个页面都解析完毕后再运行(但是遇到 script 标签就会下载对应的资源,页面都解析完毕意味着浏览器解析到结束的 </html>
  • 即使加了 defer ,script 的资源代码执行还是会在 DOMContentLoaded 时间之前执行
<script defer src="js1.js"></script>
// 对于 XHTML 文档,defer 属性应该写成。defer="defer"
// 对于 XHTML 文档,async 属性应该写成。async="async"

异步执行脚本 async

  • async 属性和 defer 属性,都会告诉浏览器立即开始下载,但是 async 的脚本并不能保证按照他们出现的次序执行
  • 适用于没有依赖关系的 js 资源,异步脚本不应该在加载期间修改 DOM
  • 异步脚本保证会在 页面的 load 时间前执行,但可能会在 DOMContentLoaded 之前或者后。

动态加载 js

除了使用 <script> 标签,js 还可以借助 DOM API 向 DOM 中动态添加 script 元素

// 默认创建的 script 元素是以异步的方式加载的,相当于添加了 async 属性,
const script = document.createElement("script");
script.src = "xxx.js";
// 可以设置 async 属性 为 fase,统一动态加载脚本的行为 script.async = fasle
document.head.appendChild(script);

以这种方式获取的资源对浏览器预加载是不可见的,这会严重影响他们在资源队列中的优先级,要想让预加载器知道这些动态请求文件的存在,可以在文档头部显示声明他们

<link rel="preload" href="xxx.js"> // 让预加载器知道这些动态请求文件的存在