onload與setTimeout的一個小問題
面試的時候遇到了這樣一個問題,如下的html頁面,最終頁面上輸出的是什麼?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>DOM載入順序</title> <script src="../libs/jquery.min.js"></script> </head> <body> <p>1</p> <script> document.write('2') </script> <p>3</p> <script> window.onload = function () { document.write('4'); document.write('5'); setTimeout(function () { document.write('8') }, 1000) }; setTimeout(function () { document.write('6') }, 0); setTimeout(function () { document.write('7') }, 1000) </script> </body> </html>
|
|
|
想
一
想
|
|
|
先不說答案,我當時的答案和思路是這樣的:
最後頁面展現的是:45678
分析:123的順序很好理解,這時候window.load
函式還沒有執行,但是在第二段指令碼中,setTimeOut
和window.onload
都是在DOM完全載入完畢後執行,document.write
相當重新書寫了頁面,導致123
被取消,在頁面上消失
你認為對嗎?
自己把這段程式碼複製到IDE中,開啟一個頁面看一看吧?
最終的結果是頁面上只展現了6和7,原因是:頁面從上向下解析,首先出現1,然後繼續解析,遇到了document.write('2')
,所以螢幕上出現2,然後繼續解析,出現3
接著遇到了<srcipt>
標籤,onload的函式肯定會暫緩執行,因為這時候頁面還沒有解析完成,然後遇到了延時0s的document.write('6')
,放入任務隊列當中,然後又將延時1s的document.write('7')
放到了任務佇列。這時候,肯定延時0s的document.write('6')
比頁面解析完成的更快,所以先執行了,這樣直接就將頁面重寫了,window.onload
這段程式碼根本就被重寫了,這時候頁面是這樣的:
<html> <head></head> <body>6</body> </html>
1s後變成了:
<html>
<head></head>
<body>67</body>
</html>
所以最終輸出結果是67
其實最終輸出的關鍵在於document.write('6')
的延時與DOM解析完畢誰先完成,和瀏覽器的解析速度有關
我試驗了一下,對於這樣一個既簡單的頁面,chrome解析大概需要100ms,所以如果document.write('6')
的延時小於100ms就會出現上面的結果,如果大於100ms的話(比如200ms),頁面最終顯示的就是45678
7和8的順序,聰明的你應該理解吧。