async和defer
js在html中的引用方式
1.内联js:直接写在我们的html文件里
2.外联js:通过script标签的src属性加载外部的资源
内联和外联js的区别
内联的缺点
1.内联js由于不使用静态资源加载的方式,所以无法缓存。
2.内联的js无法使用defer和async两个属性
3.内联的js无法被多个页面共享,造成代码的冗余,也不方便后期的维护。
4.写在html中会增加html的大小,也会影响下载页面的时候的性能
内联js的优点
1.可以减少http请求的数量
2.避免了外部js无法下载页面显示不正常的问题
常见内联js使用的情况
1.埋点数据的统计。
2.模板中埋入全局的一些变量,可能和我们访问的url中参数的不同相关联。
外联js的属性async和defer
我们常见的js代码书写位置
1.head标签里面:浏览器发现head中的script,停止html的工作,下载并执行js。
2.body标签里面:浏览器执行完dom的解析,发现了body里的js,开始下载执行。(那其实写在body标签和html标签中间的js和写在body里面是一样,)
可见放在head中的js会阻碍html的解析,那放body中不是问题就得以解决了??放body中显然还是有一些问题,我们html解析完成才会去下载js。最优的办法是一遍解析一遍下载js。
将script标签写在header,通过加上async和defer来实现异步下载
async和defer的区别
async: 异步下载,下载完成就执行,所以不能保证js的执行顺序和书写位置一样,在window的load事件之前执行完成。
defer:异步下载,等html解析完后执行,执行顺序和书写的一样。相当于是在body的尾部插入了一段script的引用。在DOMContentLoaded事件之前执行完成。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script defer=true type="text/javascript" src="./111.js"> </script> <script async type="text/javascript" src="./222.js"> </script> <script type="text/javascript"> console.log(333) </script> </head> <body> <script> console.log(4444) </script> <script defer type="text/javascript" src="./555.js"></script> </body> </html>
已上代码的输出结果是
其中111和222的执行顺序不一定,主要和js的下载速度相关,以及html解析的快慢相关。
情况一:html还没有解析完,111.js和222.js都下载完毕了,那么就会停下html解析执行222.js,执行完城后继续解析html,html解析完成执行111.js。
情况二:html解析完,111.js和222.js才下载完,那么就是按照书写顺序执行。
使用defer相当于把下载完成的js文件放入了一个队列(先进先出),在html解析完成之后开始执行队列中的js。
可以思考一个问题,其中有一个defer引入的js文件加载了特别长的时间,其余的defer会等待这个js加载吗?(我觉得是会的,也不知道是不是)