JavaScript 是如何工做的系列——第一篇
咱們都知道在默認狀況下,JavaScript 的下載和執行會阻塞 HTML 的解析,結果會致使從打開頁面到顯示出網頁內容的過程耗時較長,用戶體驗很差。本篇文章主要介紹了 JavaScript 的下載和執行是如何阻塞 HTML 解析的 ,以及如何避免阻塞。javascript
咱們如下面這段代碼爲例:html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Demo</title> <script src='./js/index1.js'></script> <script src='./js/index2.js'></script> <script src='./js/index3.js'></script> </head> <body> <div>Downloading Scripts to Execution</div> </body> </html>
index1.js 文件內容:java
console.log('index1');
index2.js 文件內容:git
console.log('index2');
index3.js 文件內容:github
console.log('index3);
當咱們在瀏覽器中打開上述 HTML 文件以後,瀏覽器就會開始解析 HTML 代碼。當瀏覽器遇到 <head> 標籤中的第一個 <script> 標籤(index1.js)後,HTML 的解析會暫停。此時瀏覽器會發送一個 HTTP 請求去下載 index1.js 文件,當腳本下載完成,瀏覽器開始解析並解釋執行下載的腳本( index1.js)。當 index1.js 執行完畢,瀏覽器繼續解析 HTML 代碼。當遇到第二個 <script> 標籤(index2.js)後,處理過程同上,後面依次類推。瀏覽器
因而可知,腳本的數量與消耗的時間是成正比的。在<head> 標籤中引入的腳本越多,用戶等待的時間越長。async
那麼有什麼辦法能夠解決上述問題呢?ui
最多見的方式就是將 <script> 標籤放到 HTML 文檔最後,</body>標籤以前。這會提升網頁加載速度,由於 HTML 加載再也不受制於腳本加載,當 HTML 內容解析完畢後,纔會開始加載腳本。spa
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Demo</title> </head> <body> <div>Downloading Scripts to Execution</div> <script src='./js/index1.js'></script> <script src='./js/index2.js'></script> <script src='./js/index3.js'></script> </body> </html>
固然還有兩種方式能夠解決上述問題:(只適用於外部腳本)線程
使用 defer 屬性後:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Demo</title> <script defer src='./js/index1.js'></script> <script defer src='./js/index2.js'></script> <script src='./js/index3.js'></script> </head> <body> <div>Downloading Scripts to Execution</div> </body> </html>
使用 async 屬性後:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Demo</title> <script async src='./js/index1.js'></script> <script async src='./js/index2.js'></script> <script src='./js/index3.js'></script> </head> <body> <div>Downloading Scripts to Execution</div> </body> </html>
從上圖中能夠看到,JavaScript 腳本的執行順序是:index1.js -> index3.js -> index2.js,這可能與你預想的執行順序不一樣。這是由於使用 async 屬性的腳本,其執行順序與文件大小、下載速度、解析速度等息息相關。
本文示例代碼已上傳到 github,感興趣的讀者能夠自行下載。本地運行後,觀察使用不一樣的方式引入 JavaScript 腳本後,頁面的加載速度。
本篇文章主要介紹了瀏覽器是什麼時候開始下載和執行 JavaScript 的 ,以及阻塞 HTML 解析問題。下篇文章將深刻 JS 引擎,瞭解 JavaScript 代碼執行的具體流程。敬請期待。
參考:
The Journey of JavaScript: from Downloading Scripts to Execution - Part I