《JavaScript高级程序设计(第四版)》p13-p15
参考链接:https://blog.youkuaiyun.com/qq_30376375/article/details/96510759?utm_source=app
1. 标签位置
如果把所有JavaScript文件都放在<head>里,也就意味着必须把所有JavaScript代码都下载、解析和解释完成后,才能开始渲染页面(页面在浏览器解析到<body>的起始标签时开始渲染)。对于需要很多JavaScript的页面,这会导致页面渲染的明显延迟,在此期间浏览器窗口完全空白。为解决这个问题,现代web应用程序通常将所有JavaScript引用放在<body>元素中的页面内容后面。这样一来,页面会在处理JavaScript代码之前完全渲染页面,用户会感觉页面加载更快了,因为浏览器显示空白页面的时间短了。
总结:就是JS代码的下载和执行都会阻塞页面的解析,所以应该把<script>标签放在最后
2. 推迟执行脚本--defer属性
在<script>元素上设置defer属性,相当于告诉浏览器立即下载,但延迟执行,脚本会在浏览器解析到结束的</html>标签后才会执行,但在DOMContentLoaded事件之前执行。
添加defer属性的<script>会按照它们出现的顺序执行,不过在实际当中,推迟执行的脚本不一定总会按顺序执行或者在DOMContentLoaded事件之前执行,因此最好只包含一个这样的脚本。而且旧版浏览器会忽略这个属性,还是把要推迟执行的脚本放在页面底部比较好。
总结:defer的下载不会阻塞页面的解析,下载完成后会推迟到页面解析完成后执行
3. 异步执行脚本--async属性
给脚本添加async属性的目的是告诉浏览器,不必等脚本下载和执行完后再加载页面,同样也不必等到该异步脚本下载和执行后再加载其它脚本。标记为async的脚本并不保证能按照它们出现的次序执行。异步脚本不应该在加载期间修改DOM。
异步脚本保证会在页面的load事件前执行,但可能会在DOMContentLoaded之前或之后执行。
结论:async属性,异步下载不会阻塞页面解析,先下载完的先立即执行,若在页面解析阶段下载完毕则会阻塞页面解析
注意:async和defer同时出现时,脚本的行为类似于async
4. 动态加载脚本
JavaScript可以使用DOM API,所以通过向DOM中动态添加script元素同样可以加载指定的脚本
let script = document.createElement('script')
script.src = 'other.js'
document.head.appendChild(script)
以这种方式获取的资源对浏览器预加载器是不可见的,可以在文档头部显式的声明:
<link rel="preload" href="othre.js">