常用属性
以下是我认为在平时会使用到的一些属性
- src
- async
- defer
- type
- integrity
- crossorigin
script执行过程(async defer)
引入方式
script在HTML有两种添加添加方式
- 使用
script
的src
属性将js文件通过链接引入 - 将js写在
<script></scritp>
里
两种引入方式的比较
- 可维护性:外置 Javascript 文件可以被多个页面调用而不用在每个页面上反复地书写.如果有需要改变的部分,你只需要在一处修改即可.所以外置JavaScript 导致代码工作量减少,进而使得维护手续也更加方便。
- 可缓存:浏览器能够根据具体的设置缓存链接的所有外部 JavaScript文件。也就是说,如果有两个页面都使用同一个文件,那么这个文件只需下载一次。因此,最终结果就是能够加快页面加载的速度。
- 关注点分离:将 JavaScript 封装在外部的.js文件遵循了关注点分离的法则.总体来说,分离 HTML,CSS 和 JavaScript 从而让我们更容易操纵他们.而且如果是多名开发者同步工作的话,这样也更方便。
加载顺序
要说到script的加载顺序就要先说标签的位置
有defer或者async的情况在后面说
放在head里面
这是传统的做法, 放在这里面会导致所有的JavaScript代码都被 下载 解析 执行 完毕后才会在页面显示内容, 在这段时间页面将一直都是白屏状态, 导致用户的体验非常差.
浏览器在解析到body标签才会解析类容
放在body元素内的最后面
这种在解析JavaScript代码之前, 页面已经完全呈现在浏览器中了, 由于空白页时间变短而感到页面打开的速度加快了.
像js一些对dom的操作强烈建议放在body元素内的最后面, 防止在操作dom节点的时候dom未加载出来,出现报错; 在dom加载完毕之后不会重新回到头部执行script,对dom的操作效果显示不出来.
async 与 defer
async和defer的方式都只对外部脚本是有效的
async
表示应该立即开始下载脚本,但不能阻止其他页面动作,比如下载资源或等待其
他脚本加载, 下载完毕后开始执行. 不会等待
- 下载不会阻塞页面解析
- 保证会在页面的 load 事件前执行,但可能会在 DOMContentLoaded之后执行
- 多个async存在时, 谁先下载完成谁先解析
- 在执行时可能有的页面还没有解析完成
由此, 异步脚本不应该在加载期间修改dom
defer
表示脚本可以延迟到文档完全被解析和显示之后再执行
- 不会阻塞页面解析
- 在html解析完成之后(DOMContentLoaded之前)执行
- 按照顺序执行
类型为模块(type="module")的标签
mozilla文档
现代JavaScript教程--什么是模块
在标记了类型为模块之后, 这个标签的内容将被当作JavaScript模块看待
module为异步加载, 不会造成堵塞, 等同与defer属性, 使用相同的执行队列, 谁在前面谁先执行.
具体关于模块的知识点, 在后面专门写一篇来说
integrity 属性
<script integrity="sha256-pojweihxfdkseiwelsfsadknf=" src="xxx"></script>
integrity
属性是资源完整性规范的一部分,它允许你为script提供一个hash,用来进行验签,检验加载的JavaScript文件是否完整。
在上面的例子是告诉浏览器使用sha256签名算法对下载的js文件进行计算,并与intergrity
提供的摘要签名对比,如果二者不一致,就不会执行这个资源。
作用:
- 减少由【托管在CDN的资源被篡改】而引入的XSS 风险
- 减少通信过程资源被篡改而引入的XSS风险(同时使用https会更保险)
- 可以通过一些技术手段,不执行有脏数据的CDN资源,同时去源站下载对应资源
crossorigin属性
mozilla关于这个属性的中文文档翻译质量不好, 缩减了一些方便理解的内容, 因此以英文文档为准
crossorigin属性有2个值 anonymous
use-credentials
crossorigin="anonymous"
- 使用CORS
credentials flag
设置为same-origin
在同源的情况下才会发送cookie等凭据
crossorigin="use-credentials"
- 使用CORS
credentials flag
设置为include 总是会发送cookie等凭据(跨域)
crossorigin="" 或者等于一个错误的值
- 与
anonymous
属性相同
没有crossorigin属性
- 不会使用
CORS
- 通过 window.onerror 访问错误日志将受到限制。
关于credentials flag 这里关系到CORS的一些详情 我的理解是 在请求的时候类似于:
带credentials的 Fetch :
fetch(url, {
credentials: 'include'
})
以及带credentials的 XHR :
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);
Credentials必须在前后端都被配置(即the Access-Control-Allow-Credentials header 和 XHR 或Fetch request中都要配置)才能使带credentials的CORS请求成功。
附上跨域相关的文档, 后面可能会用到:
Mozilla crossorigin
Mozilla Access-Control-Allow-Credentials
Request.credentials
预检