1.Web浏览器根据URL地址下载文档内容,并创建Document对象,解析WEB页面,HTML元素,包含的文本内容,将这些节点添加到DOM树中。在这个阶段,document.readystate属性的值是 loading。
2.当解析器遇到没有async和defer属性的<script>元素时,它把这个元素添加到DOM树中,并且开始执行其中的JavaScript脚本,这些脚本会被同步执行,并且在下载(通过src属性引用的外部js)和执行的过程中,解析器会暂停。所以在这些脚本中可以使用document.write()方法把内容插入到输入流中,解析器在恢复解析的时候会把这些内容当成文档的一部分。可以看到这里的脚本可以看到它自己的<script>元素,以及它们之前的文档内容
3.当解析器遇到设置了async属性的<script>元素时,它开始下载脚本文本,但解析器会继续解析文档。在这些脚本中就不能再使用document.write()方法了。这些脚本同样可以访问到自己的<script>元素和之前的所有文档元素。由于这些脚本在下载完成后立刻执行,所以可能不能访问它之后的其他文档内容。
4.当文档完成解析后,document.readyState属性变成 interactive
5.当解析器遇到设置了defer属性的<script>元素时,它同样会下载脚本文本,并继续解析文档。不过这里的脚本会在文档完成解析后按照先后顺序执行,所以可以访问完整的文档树,当然document.write()方法还是无法使用的
6.浏览器在Document对象上触发DOMContentLoaded事件,这也标志着JavaScript的执行从同步执行阶段转换到了异步事件驱动阶段,不过在这个阶段async属性的脚本可能还没有执行完成。
7.到这里,文档已经解析完成,不过浏览器可能还在等待其他内容的载入,比如图片,flash等外部资源。当所有的这些外部资源完成载入,async属性的脚本执行完成,document.readyState属性变为 complete.并且触发window对象上的load事件。
8.从此刻起,会调用异步事件,已异步的方式响应用户输入事件,网络事件,计时器事件等
当然上面的这条时间线是存在于我们脑海中的一个奢望,各个浏览器在实现上都有或多或少的差异,有的可能只支持其中一部分,这里就需要通过各种判断来兼容各种浏览器!