简单说说代码加载顺序

$(function)与window.onload=a与window.onload=a()

今天被问到这样一段代码

1
2
3
4
5
6
7
8
9
10
$(function() {
alert(1)
})
window.onload = function() {
alert(2);
}
function loa() {
alert(3);
}

执行结果是【1,2,3】

为啥?!

经过百度(是的,连google都用不着)搜得一些信息,在jq里$(function(){})$(document).ready(function(){})两个方法的效果是一样的,都是在dom文档树加载完之后执行一个函数(注意,这里面的文档树加载完不代表全部文件加载完)。
window.onload是在dom文档树加载完和所有文件加载完之后执行一个函数。也就是说(document).ready要比window.onload先执行。

ok,i try try:

1
2
3
4
5
6
7
8
9
window.onload = function() {
alert('onload');
};
document.ready(function() {
alert('ready');
});

果然先弹出【ready】,后弹出【onload】。

在Jquery里面$(document).ready函数的内部是这样实现的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
document.ready = function(callback) {
///兼容FF,Google
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', function() {
document.removeEventListener('DOMContentLoaded', arguments.callee, false);
callback();
}, false)
}
//兼容IE
else if (document.attachEvent) {
document.attachEvent('onreadytstatechange', function() {
if (document.readyState == "complete") {
document.detachEvent("onreadystatechange", arguments.callee);
callback();
}
})
} else if (document.lastChild == document.body) {
callback();
}
}

了解了ready和onload的区别,所以能得到断定的是先2在1之后。
由于代码执行顺序从上往下,首先执行的onload为head内的,即为2,再次执行也就是body里的onload,即为1.故此执行结果为1,2,3。

根据我混迹多年的码农第六感,我又将head内的js部分放入body之后。

1
2
3
4
5
6
7
8
9
10
$(function() {
alert(1)
})
window.onload = function() {
alert(2);
}
function loa() {
alert(3);
}

由于此时顺序的改变,得到的结果竟然是1,2。哼,哀家就知道有诈!

前面讲到onload和ready的区别后,1,2可以理解,为啥3又不显示了?

后来发现,原来在执行2时,onload此时已经被赋予属性function(){ alert(2);}了,所以在时,虽然系统没有报错,但此时body内的onload已经不是初始的onload。
以为这样就完了么,太简单,我又把js放到头部,现在改变了一点情况:

1
2
3
4
5
6
7
8
$(function() {
alert(1)
})
window.onload = loa;
function loa() {
alert(3);
}

这个的输出结果仍然是1, 3

1
2
3
4
5
6
7
8
$(function() {
alert(1)
})
window.onload = loa();
function loa() {
alert(3);
}

这个的输出结果却是【3,1】

真是“惊喜”啊,码农的世界尊的好丰富啊~ 一个()改变世界有木有。

咱们来略较真的探讨下window.onload = a ;window.onload = a() ;的区别,前者页面加载完毕后立刻执行方法a,后者是调用方法a的执行结果赋值给onload属性,window是全局对象,onload是其属性,意思是事件会在页面或图像加载完成后立即发生

我暂时没有想到一个更好♂的比喻,尽量解释清楚:

  1. 前者: 当页面(包括文件)加载完毕后执行方法function a();此时onload的类型为function(函数)。
  2. 后者: 调用执行function a()方法的返回值赋给window.onload。此时onload已经被鬼上身(赋值)了,鬼就是为function a()执行的结果。当function a()执行的结果没有返回值,则onload类型为object(对象)。总之,它不是之前那个单纯的看不见摸不着的意识流了!

这里我建议结合我以上的说法console试试,学渣友情提醒,来跟我一起左手右手一个慢动作,一定要亲自试试不然会忘记的忘了几次的我决定今天好好写一篇记录,巩固巩固。

了解了以上区别,这样window.onload = a我们已经很好理解了。
window.onload = a() ; 之前说到“此时onload已经被鬼上身(赋值)了,那么onload便不在是当初的onload”。它被赋予了新的意义,那么原来的它(onload:事件会在页面或图像加载完成后立即发生)便不复存在。所以,可以这么理解,原本的onload没有被执行,onload被赋予了新的意义。既然没有被执行,那么它不需要等待页面加载完毕,二手页面加载到它这的时候就执行因此,输出的结果为3,1。