1. 程式人生 > >onload與setTimeout的一個小問題

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函式還沒有執行,但是在第二段指令碼中,setTimeOutwindow.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的順序,聰明的你應該理解吧。