JavaScript 複習之瀏覽器模型

DreamTruth發表於2019-03-04

網頁中嵌入 JavaScript 程式碼,主要有三種方法。

  • <script>元素直接嵌入程式碼。

  • <script>標籤載入外部指令碼

  • 事件屬性

  • URL 協議

script 元素

工作原理

  1. 瀏覽器一邊下載 HTML 網頁,一邊開始解析。也就是說,不等到下載完,就開始解析。
  2. 解析過程中,瀏覽器發現<script>元素,就暫停解析,把網頁渲染的控制權轉交給 JavaScript 引擎。
  3. 如果<script>元素引用了外部指令碼,就下載該指令碼再執行,否則就直接執行程式碼。
  4. JavaScript 引擎執行完畢,控制權交還渲染引擎,恢復往下解析 HTML 網頁。

defer屬性

他的作用是延遲指令碼執行,等到 DOM 載入生成後,在執行指令碼。

defer屬性的執行流程如下。

  1. 瀏覽器開始解析 HTML 網頁。
  2. 解析過程中,發現帶有defer屬性的<script>元素。
  3. 瀏覽器繼續往下解析 HTML 網頁,同時並行下載<script>元素載入的外部指令碼。
  4. 瀏覽器完成解析 HTML 網頁,此時再回過頭執行已經下載完成的指令碼。

async屬性

解決“阻塞效應”的另一個方法是對<script>元素加入async屬性。

async屬性的作用是,使用另一個程式下載指令碼,下載時不會阻塞渲染。

  1. 瀏覽器開始解析 HTML 網頁
  2. 解析過程中,發現帶有async屬性的script標籤
  3. 瀏覽器繼續往下解析 HTML 網頁,同時並行下載<script>標籤中的外部指令碼。
  4. 指令碼下載完成,瀏覽器停止解析 HTML 網頁,開始執行下載的指令碼
  5. 指令碼執行完畢,瀏覽器恢復解析 HTML 網頁

async屬性可以保證指令碼下載的同時,瀏覽器繼續渲染。需要注意的是,一旦採用這個屬性,就無法保證指令碼的執行順序。哪個指令碼先下載結束,就先執行那個指令碼。另外,使用async屬性的指令碼檔案裡面的程式碼,不應該使用document.write方法。

指令碼載入使用的協議

如果不指定協議,瀏覽器預設採用 HTTP 協議下載。

<script src="example.js"></script>
複製程式碼

上面的example.js預設就是採用 HTTP 協議下載,如果要採用 HTTPS 協議下載,必需寫明。

<script src="https://example.js"></script>
複製程式碼

但是有時我們會希望,根據頁面本身的協議來決定載入協議,這時可以採用下面的寫法。

<script src="//example.js"></script>
複製程式碼

瀏覽器的組成

瀏覽器的核心是兩部分:渲染引擎和JavaScript引擎

渲染引擎的主要作用是將網頁程式碼渲染為使用者視覺可以感知的平明文件。處理網頁分為四個階段:

  1. 解析程式碼:HTML 程式碼解析為 DOM , CSS程式碼解析為 CSSOM
  2. 物件合成:將 DOM 和 CSSOM 合成一個渲染樹
  3. 佈局:計算渲染樹的佈局
  4. 繪製:將渲染樹繪製到螢幕

重流和重繪

渲染樹轉換為網頁佈局,稱為“佈局流”;佈局顯示到頁面的過程稱為“繪製”。

頁面生成以後,指令碼操作和樣式表操作,都會觸發“重流”和“重繪”。

重流和重繪並不一定一起發生,重流必然導致重繪,重繪不一定需要重流。

優化技巧:

  • 讀取 DOM 或者寫入 DOM,儘量寫在一起,不要混雜。不要讀取一個 DOM 節點,然後立刻寫入,接著再讀取一個 DOM 節點。

  • 快取 DOM 資訊。

  • 不要一項一項地改變樣式,而是使用 CSS class 一次性改變樣式。

  • 使用documentFragment操作 DOM ``動畫使用absolute定位或fixed定位,這樣可以減少對其他元素的影響。

  • 只在必要時才顯示隱藏元素。

  • 使用window.requestAnimationFrame(),因為它可以把程式碼推遲到下一次重流時執行,而不是立即要求頁面重流。

  • 使用虛擬 DOM(virtual DOM)庫。

// 重繪代價高
function doubleHeight(element) {
  var currentHeight = element.clientHeight;
  element.style.height = (currentHeight * 2) + 'px';
}

all_my_elements.forEach(doubleHeight);

// 重繪代價低
function doubleHeight(element) {
  var currentHeight = element.clientHeight;

  window.requestAnimationFrame(function () {
    element.style.height = (currentHeight * 2) + 'px';
  });
}

all_my_elements.forEach(doubleHeight);
複製程式碼

avaScript 引擎的主要作用是,讀取網頁中的 JavaScript 程式碼,對其處理後執行。

相關文章