JS加载时间线
浏览器在运行一个页面时,首先会初始化js的功能,当初始化初试完js这一个功能后,也就是js开始发挥作用那一刻,开始记载着这一系列浏览器要发生的过程;
1.创建Document对象,开始解析web页面,解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段Document。readyState = “loading”
2.遇到link外部css,创建线程加载,并继续解析文档。
3.遇到script外部js,并且没有设置async , defer ,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档
4.遇到script外部js,并且设置有async,defer 浏览器创建线程加载,并继续解析文档,对于async属性的脚本,脚本加载完成后立即执行(异步禁止使用docuemnt.write())。
5.遇到img标签等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档
6.当文档解析完成,document.readyState = “interactive”;
7.文档解析完成后,所有设置有defer的脚本会按照顺序执行。
8…当文档解析完成之后,document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段
9.当所有saync的脚本加载完成并执行后,img等加载完成后,document.readyState = “complete” window对象触发load事件
10.从此,页面以异步响应方式处理用户输入,网络事件等。
以上十个步骤是js执行的全部步骤
异步的加载

DOM树的生成规则:深度优先(从左到右生成,优先生成深度比较多的节点)
浏览器渲染页面前的步骤
1.解析DOM节点,生成DOM树
2.继续解析css代码生成CSS树
3.DOM树和CSS树合并在一块生成Render树
4.浏览器开始渲染页面
(1)同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止后续的解析,只有当当前加载完成,才能进行下一步操作。所以默认同步执行才是安全的。但这样如果js中有输出document内容、修改dom、重定向等行为,就会造成页面堵塞。所以一般建议把script标签放在body结尾处,这样尽可能减少页面阻塞
(2)异步加载又叫非阻塞加载,浏览器在下载执行js的同时,还会继续进行后续页面的处理,不会造成页面阻塞;
异步加载js文件的三种方案
创建script标签,插入到dom中,加载完毕执行回调函数
<script>
function loadScript(url, callback){
var script = document.createElement('script');
script.type = "text/javascript";
//处理兼容性
if(script.readyState){ //IE9以下
script.onreadystatechange = function(){
if(script.readyState=='complete'||script.readyState=='loaded'){
callback();//obj[(callback)]()
}
}
}else{
script.onload = function () { //firefox chrome safair opera
callback();//obj[(callback)]()
}
}
script.src = url; //js文件路径
document.head.appendChild(script);
}
loadScript(url,callback)
</script>
但是这种加载方式执行完之前会阻止onload事件的触发,而现在很多页面的代码都在onload时还执行额外的渲染工作,所以还是会阻塞部分页面的初始化处理
async 异步加载
<script type="text/javascript" src="example.js" async="async"></script>
async异步加载,加载完就执行,async只能加载外部脚本,不能把js代码写在script标签里
defer 异步加载
<script type="text/javascript" src="example.js" defer="defer"></script>
defer 异步加载,但要等到dom文档全部解析完才能被执行。只有IE能用,可以把代码写在script标签里
340

被折叠的 条评论
为什么被折叠?



