對於初學者來講,window.onload並不陌生,可是對於爲何要使用它、以及不使用它會致使什麼結果,可能並無深究過,下面經過幾個實驗對比,深入理解。瀏覽器
實驗一:函數
<script> document.getElementById("me").style.color = "blue"; </script> <body> <h1 id="me">Double Zhang</h1> </body>
實驗結果是 h1字體爲原始黑色,並無被渲染爲藍色,爲何代碼沒有生效呢?工具
首先要知道,document文檔是從上向下解析執行,當執行到script時,body中的h1還未被執行和加載到網頁中,這時候 document.getElementById("me") 並無獲取到h1對象,能夠打斷點看一下,獲取的值是undefined,那就更不存在將它的字體設置爲藍色了。性能
實驗二:測試
<body> <script> document.getElementById("me").style.color = "blue"; </script> <h1 id="me">Double Zhang</h1>
</body>
是否是把script標籤放到body裏就能夠獲取到元素了呢?實驗結果字體依舊是原始的黑色。字體
「document文檔是從上向下解析執行」,當執行script時,h1仍舊沒有被加載。spa
實驗三:code
<body> <h1 id="me">Double Zhang</h1> <script> document.getElementById("me").style.color = "blue"; </script> </body>
實驗結果字體爲藍色,終於渲染成功。對象
注意,此次代碼執行的順序有所改變,先將h1標籤渲染進DOM樹,接着纔是經過JS獲取,因此獲取到了該元素,接着改變字體顏色。blog
實驗四:
<script>
window.onload = function(){ document.getElementById("me").style.color = "blue"; }
</script>
<body> <h1 id="me">Double Zhang</h1> </body>
實驗結果:JS代碼仍是在body標籤前面,講道理這時候是獲取不到h1標籤的,可是此次渲染成功了,字體爲藍色。
仔細看過代碼後發現這次實驗使用了window.onload,這是成功渲染的關鍵,這裏有必要解釋一下window.onload了,它表示:網頁完成了DOM樹的建立以及網頁中圖片等外部資源的加載。其中完成DOM樹的建立能夠保證咱們能經過getElementById方法在DOM樹中找到元素,這就是爲何實驗四可以成功渲染藍色字體。
有了這個神器,媽媽不再用擔憂寫在HTML前面的JS代碼獲取不到咱們想要的元素了,不過先別高興的太早,由於這裏存在一個隱患,window.onload中的代碼不只是在DOM樹建立後執行,並且還要等到圖片資源加載完成,那麼當頁面中須要加載的文件(圖片、文本……)很是多的時候,window.onload裏面的代碼就遲遲沒法執行,這將帶來不好的用戶體驗,因而咱們會思考,咱們只是想經過JS代碼操做DOM,與圖片並無關係啊,因此能不能讓DOM樹一建立完成就執行代碼而不用等圖片加載完畢呢?畢竟咱們都想讓本身的網頁性能更好一些、加載更快一些、用戶體驗更好一些,那就接着往下看吧。
實驗五:
<script> setTimeout(function(){ document.getElementById("me").style.color = "blue"; },3000); </script> <body> <h1 id="me">Double Zhang</h1> </body>
實驗結果:字體成功渲染爲藍色,並且沒有使用window.onload。
這裏作了一個定時器的3秒延時,在這3秒裏,頁面完成了DOM樹的建立,因此h1元素被成功獲取到了,再添加顏色就沒問題了,可是在這3秒裏該網頁的圖片資源有沒有所有加載完成並不能肯定,不過至少DOM樹是建立完成了,不然實驗結果不會正確。(注意這個3秒的取值是隨便取的,沒有任何規定,純屬測試)
細心的人會發現這個實驗有點小問題,運行代碼,會看到字體會閃一下,閃以前爲黑色,閃以後變爲藍色,由於頁面剛呈現時h1默認爲黑色,三秒時代碼生效,字體被設置爲紅色。這種用戶體驗並很差,不知是否能夠改進?
總結一下這種方法的兩大隱患,第一,由於咱們沒法把握DOM樹完成建立的準確時間,就意味着咱們不能避免「閃一下」的問題,和實驗五同樣,假如咱們設置的延遲大於DOM完成建立須要的時間,那頁面就會閃一下;第二,假如咱們設置的setTimeout延遲時間小於DOM樹完成建立須要的時間,DOM未建立好,那麼字體也不會被渲染爲藍色。帶着消除隱患的念頭,接着往下看吧。
實驗六:
<script> $(document).ready(function(){ document.getElementById("me").style.color = "blue"; }); </script> <body> <h1 id="me">Double Zhang</h1> </body>
實驗結果:字體成功渲染藍色,使用了jQuery的$.ready()方法。
說到這裏,本篇文章的大BOSS終於出場了(腦中請自行響起BGM)。
$.ready(),它表示:在DOM樹建立完成後(HTML解析的第一步)就觸發代碼,無需等待頁面中其餘資源(圖片等)的加載。
到此,以前咱們實驗中遇到的顧慮都被解除了,首先,不用擔憂代碼取不到DOM中想要的元素了,代碼不會再失效了;其次,DOM樹一建立完成就執行了代碼,不用等圖片等資源的加載完成了,效率很高;再次,不用人爲的加定時器去延遲加載了,也就不用擔憂定時器的延遲時間拿捏的準不許了。哎,簡直不要太開心,這麼好的工具,難道不想試着本身造一個嗎?
本身模擬一個jQuery的ready方法:
function myReady(fn){ //利用能力檢測區分瀏覽器 if(document.addEventListener){ document.addEventListener("DOMContentLoaded",fn,false); } else{ //這裏是IE低版本瀏覽器 IEContentLoaded(fn); } //IE模擬DOMContentLoaded function IEContentLoaded(fn){ var d = document.window; //保證fn回調函數只執行一次 var done = false; var init = function(){ if(!done){ done = true; fn(); } } (function(){ try{ //DOM樹未建立前調用doScroll會拋出異常 d.documentElement.doScroll('left'); } catch(e){ //arguments.callee指向這個便可執行的(function(){})(); //沒有捕獲異常意味着DOM成功建立,就能夠執行回調函數了 setTimeout(arguments.callee,60); return; } })(); //監聽document的加載狀態 d.onreadystatechange = function(){ if(d.readyState == 'complete'){ d.onreadyState == null; init(); } } } }