JS时间线
我们知道JS是一个单线程的语言,从上到下依次同步执行,那么这期间到底发生了什么呢?
JS时间线
1、创建document对象,开始解析页面。创建HTMLHtmlElement对象,添加到document中。此时,document.readyState = ‘loading’,准备进入加载阶段。
2、遇到link外部CSS,遇到link外部css,创建线程并加载,之后继续解析文档。并发过程。
3、遇到script外部js,并设置有async、defer属性。创建线程加载,并继续解析文档。这里,实际上是通过 document.createElement(‘script’) 方式动态插入script元素,来模拟async属性(异步),实现了脚本异步加载和执行。而defer属性(延迟)是指创建线程加载,等到DOM结构加载完成后才会执行。
4、如果遇到script外部js,没有设置async、defer属性。那么浏览器将会创建线程加载并产生阻塞,等待js加载完成并执行完脚本才会继续解析文档。(同步加载,阻塞加载) 因此,一般我们会把较为复杂的js文件放到尾部执行。此时这样的脚本可以采用 document.write() 的方式把文本插入到输入流中,成为文档的一部分。

5、遇到image、声音等资源时,浏览器会创建单线程加载,并继续解析文档。并发。
6、此时,当文档解析完成(DOM结构完成),document.readyState = ‘interactive’,准备进入交互阶段。
7、文档解析完成后,所有defer属性的脚本就会按顺序依次执行。延迟脚本(即带有defer属性的脚本)能访问到完整的DOM树。此时,禁止使用 document.write() 方法。
8、document对象触发DOMContentLoaded事件,标志着程序执行从同步脚本执行阶段转换为事件驱动阶段(异步)。(注意,这里仍然可能会有异步脚本未完成加载。)
9、此时文档已全部解析完毕,但是浏览器还在等待其他内容载入。当所有的异步脚本执行和image等资源加载完成之后,document.readyState = ‘compelete’,文档、脚本、资源此时全部完成,浏览器触发window对象的load事件。即我们在js代码中常写的window.onload。
10、从此刻起,会调用异步事件。以异步的响应方式处理用户输入、网络、计时器等事件。