在理解async,defer,ready,onload之前,首先需要知道浏览器执行html过程中包含的步骤,以及存在的机制和事件。本文结合实际代码,调试分析它们的作用与区别。
1 执行时间轴
浏览器中按下“F12”,点击Network,即可查看刷新网页时的时间流程
下载资源(Finish)--> DOMContentLoaded-->Load
下载的资源:包含html,css,js文件,用于构建页面,时间与服务器性能,网络质量有关;
DOMContentLoaded:表示DOM生成完,解析完HTML文件,时间与HTML中js位置,HTML文件复杂度有关;
Load:表示加载完成,包含图片,字体,视频等资源,世间与资源大小有关。
DOMContentLoaded与Load的时间节点分别对应ready事件与onload事件。
defer关键字也与DOMContentLoaded有关。
2 html到DOM
浏览器把从服务器端获取的html文件按照顺序,从上至下的进行解析,生成DOM。
当遇到<script>标签时,会阻塞DOM的生成,此时会去下载js文件并执行,浏览器处于空白状态。
为了解决这个问题,在HTML5中加入了async,defer关键字,目的都是为了防止阻塞DOM生成,而导致浏览器页面处于空白。当然,如果js文件比较小,下载和执行较快时用户感觉不出来。
3 async 与 defer
async表示异步,指的是当执行html时,遇到<script>标签,不阻塞DOM的生成,同时异步下载js文件,当下载完成时执行js文件,所以使用async时,js的执行时间点是不受控制的,是无顺序的,因为什么时间会下载完成,谁也无法确定。
defer表示推迟执行,那么推迟至何时执行呢?
在1节的时间轴中,defer将js文件推迟至DOMContentLoaded时执行,也就是说此时的页面渲染完成,不会因为执行js而导致页面空白。和将js文件放在body的最后面有几乎同样的效果。
所以如果js的执行有依赖关系,有先后执行的顺序要求,尽量不要使用async,因为时间不可控。
4 ready 与 onload
有了1节的时间轴概念,很容易理解ready,onload之间的差异。
对于执行顺序来说:
ready在DOMContentLoaded完成后触发;
onload在Load完成后触发。
对于执行次数来说:
ready函数有几个会执行几个,不会冲突与覆盖;
onload函数,后面的会覆盖前面的,也就是只会执行最后的onload函数一次。
5 试验(调试环境为chrome)
<head>
<script type="text/javascript" src="js/jquery.js"></script>
<script defer type="text/javascript" src="js/mav.js"></script>
<script>
console.log("jascript up...");
</script>
</head>
<body>
<label> aaaaa <label>
<script type="text/javascript">
window.onload = function(){
console.log("onload1...");
};
window.onload = function(){
console.log("onload2...");
};
$(document).ready(function(){
console.log("$ ready1...");
});
$(document).ready(function(){
console.log("$ ready2...");
});
//initialize:
$(function () {
}
console.log("jascript down...");
</script>
</body>
执行效果:观察log
1.虽然mav.js在前面,由于defer推迟执行,所以首先执行head中的内联js代码;
2.执行body底部的内联js代码;
3.此时DOM生成完成,触发DOMContentLoaded。执行初始化函数,初始化可以用$(document).ready(function(){}), $(function(){} 这两种。都是表示DOMContentLoaded触发的事件所执行的函数,并且可以多次执行。$ ready1... and $ ready2...
4.与此同时(DOMContentLoaded),defer修饰的mav.js也开始执行。
5.Load事件,触发执行window.onload函数,不可多次执行,只执行最后一次,覆盖前面。
手工码字不易,若有帮助,还请多多点赞支持O(∩_∩)O