上次在别人的博客看到一篇关于JS执行顺序的文章,觉得挺有道理,加上最近又碰上个关于这个的难题,就借着别人的例子研究了一下,写个博文记录下。
参考链接:http://747017186.iteye.com/blog/1977133
JS代码可以在html代码的<head>和<body>里面引用,所以按照解析html代码的先后顺序来决定JS的执行先后顺序,可以看下面的一段代码来验证:
不使用Jquery的情况下:
<html>
<head>
<title>测试JS的执行顺序</title>
<script type="text/javascript">
alert("最先执行");
</script>
<script type="text/javascript" src="temp.js" charset="UTF-8"></script>
</head>
<body οnlοad="alert('最后执行');">
<script type="text/javascript">
alert("中间执行1");
</script>
测试JS的执行顺序
<script type="text/javascript">
alert("中间执行2");
</script>
</body>
</html>
temp.js
alert("谁先引用?谁先执行!");通过上面的代码,可以得出以下结论:
1.在<head>里面的JS谁先被引用,谁就优先执行,在本例中外部引用的JS第一个执行。紧接着下面的一个<script>“最先实行”代码执行。
2.在<body>里面的JS要比<head>里面的JS后执行,因为html代码是先执行<head>再执 行<body>的,紧接着执行“中间执行1”,然后页面上执行html代码“测试JS的执行顺序 ”,再按照顺序执行“中间执行2”的JS代码。
3.最后页面全部加载完成之后,就是从<head>一直到<body>全部执行完,触发页面加载完成函数onload(),然后执行“最后执行”JS。
使用Jquery的情况下:
<html>
<head>
<title>测试JS的执行顺序</title>
<script type="text/javascript" src="jquery.min.js" charset="UTF-8"></script>
<script type="text/javascript">
alert("最先执行");
</script>
<script type="text/javascript" src="temp.js" charset="UTF-8"></script>
<script type="text/javascript">
$(document).ready(function(){
alert("到底谁先执行");
});
</script>
</head>
<body οnlοad="alert('最后执行');">
<script type="text/javascript">
alert("中间执行1");
</script>
测试JS的执行顺序
<script type="text/javascript">
alert("中间执行2");
</script>
</body>
</html>
temp.js
$(function(){ alert("谁先引用?谁先执行!"); });
在引入Jquery之后,执行顺序的基本原则还是一样的,谁先被引用谁就优先执行,所不同的是:$.(function)方法要在onload()方法之前执行。
总结:JS的执行顺序,由HTML的加载顺序决定,谁先被引用谁就优先执行(无论是写在页面上的JS代码还是引入的JS文件),最后执行onload()方法。如果有Jquery的$(function)或者$(document).ready(function(){}),其原则跟上面的原则一致,有出入的是:她优先onload()方法执行。
这里有一个实际应用。
有时候在页面结构为:上表单+下列表时,需要给列表留一定的高度来显示数据,这时候就需要根据页面的高度、表单的高度来计算给列表预留的高度。Jquery的$(obj).offset().top很好用,但有一个缺点:兼容性问题。IE和火狐的解析差距很大。为了兼容,通常使用类似于下面的代码:
function pageX(elem){ //left return elem.offsetParent ? elem.offsetLeft + pageX(elem.offsetParent) : elem.offsetLeft; } function pageY(elem){ //top return elem.offsetParent ? elem.offsetTop + pageY(elem.offsetParent) : elem.offsetTop; }
其中elem是需要进行计算的对象。
很明显,这个有判断,而且用了递归,能解决兼容性问题,不过也有个问题:时差问题。如果直接将这些代码放在$(function)方法里面(或者$(document).ready(function(){})),它的结果跟offset().top,offset().left是一样的,具体什么原因,不用我说了吧(因为东西还没加载完啊,真正加载完是在触发onload()方法之后)。怎么办呢?可能你会想到用延时,也就是setTimeout,让它过一段时间之后再计算,这也行,也能计算的对,如果你不急着用这个计算出来的数据的话并且你的这些计算代码后面没有代码要执行的话。很明显,这不可能,因为我们计算出来这个数据,就是作为基础数据用来计算后面的,延时不能用了。可以用alert,alert出来的时候,就加载完了,数据就计算对了,可是这个alert不友好啊。怎么办呢?是的,用onload(),将这段代码放在onload()里面,也就是等页面完全加载完了再计算,这个时候递归所需要的各种offsetParent都加载完了,也就没问题了。