幾個 JavaScript 效能優化小 Tip

知識小集發表於2020-03-05

本文翻譯自 John Au-Yeung 的 JavaScript Best Practices — Performance,請參考原文閱讀

像任何其他程式語言一樣,JavaScript 也有自己的最佳實踐列表,以使程式更易於閱讀和維護。JavaScript 有很多棘手的部分,因此應避免某些降低程式碼質量的做法。通過遵循最佳實踐,我們可以建立優雅且易於管理的程式碼,讓任何人都可以輕鬆使用。

在本文中,我們將探討提高應用程式效能的方法,包括將資料快取在變數中,使用最快的方法迴圈遍歷變數,減少 DOM 訪問和頁面上的元素,並推遲指令碼載入。

減少對變數和屬性的訪問

我們應該減少訪問應用程式中變數和物件屬性的次數。

這是因為每次執行此操作時,CPU 都必須一次又一次地訪問記憶體中的專案以計算其結果。

因此,我們應該儘可能少地這樣做。

例如,對於一個迴圈,不應像下面這樣:

for(let i = 0; i < arr.length; i++) {
}
複製程式碼

而應該寫成:

let length = arr.length;
for (let i = 0; i < length; i++) {

}
複製程式碼

這樣,arr.length 在我們的迴圈中僅被引用一次,而不是在每次迭代中都對其進行訪問。

迴圈遍歷變數的最快方法

在 JavaScript 中,有多種方法遍歷可迭代物件。一種是老的 for 迴圈,其他方法包括 for...of 迴圈,陣列的 forEach 方法。map 和 filter 操作也會遍歷陣列。還有 while 迴圈。

在執行迴圈的所有方式中,for 迴圈是最快的方式,無論是否像上面一樣快取 length,for 迴圈都是如此。但是,快取 length 有時會使迴圈執行得更好。

一些瀏覽器引擎在不快取 length 屬性的情況下優化了 for 迴圈。

遞減索引的 whil e迴圈比 for 迴圈慢大約 1.5 倍。

使用 forEach 迴圈的速度比 for 迴圈慢 10 倍,因此最好避免使用它,尤其是對於大型陣列。

我們可以在這裡看到結果。

減少 DOM 訪問

訪問 DOM 是一項昂貴的操作,因為瀏覽器必須從網頁中獲取元素,然後從中建立一個物件並返回它。

為了減少 DOM 訪問,如果我們需要多次操作 DOM Node 物件,則應該將其賦值給變數。

例如,如果我們有以下 HTML,並且希望在幾秒鐘後為其設定一些文字:

<p id='foo'>
</p>
複製程式碼

我們可以編寫以下程式碼來做到這一點:

const setText = (element, textContent) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      element.textContent = textContent;
      resolve();
    }, 3000)
  })
}
(async () => {
  const foo = document.querySelector('#foo');
  await setText(foo, 'foo');
  await setText(foo, 'bar');
  await setText(foo, 'baz');
})();
複製程式碼

在上面的程式碼中,我們有一個函式來獲取我們要操作的 HTML 元素以及要設定的文字內容。

setText 函式返回一個 promise,並將在 3 秒後將文字設定為給定元素。

然後我們有一個 async 函式來設定文字 3 次。核心部分是我們在每次呼叫時都將元素的引用傳遞給它。這樣,我們不必每次從網頁上獲取元素,這是一項昂貴的操作。

減少DOM大小

DOM 樹渲染起來很慢。因此,我們必須減小樹的大小。

這個別無選擇,只能使我們的網頁儘可能簡單。

DOM 較小時,由於查詢內容較少,因此可以使用 querySelector,getElementById 或 getElementsByTagName 之類的方法更快地搜尋元素。

此外,由於載入的內容更少,因此頁面渲染效能也會提高。對於手機和平板電腦等速度較慢的裝置尤其如此。

不要宣告不必要的變數

每次我們宣告變數時,瀏覽器都必須為變數分配儲存空間。因此,為了減少記憶體使用,我們不應該宣告太多變數。

例如,如果我們有以下 HTML:

<div id='foo'>
  <p>
  </p>
</div>
複製程式碼

我們想設定 p 元素的文字內容,我們不應該這樣寫:

const foo = document.querySelector('#foo');
const p = foo.querySelector('p');
p.textContent = 'foo';
複製程式碼

因為我們這裡有 2 個變數,這意味著我們的計算機必須額外儲存 2 個 JavaScript 變數的值。

我們可以通過編寫以下程式碼來減少變數宣告:

document.querySelector('#foo p').textContent = 'foo';
複製程式碼

如我們所見,我們可以使用 querySelector 方法通過 CSS 選擇器選擇任何內容。這意味著我們應該使用此方法和相關的 querySelectorAll 方法來選擇元素,因為它們都可以使用 CSS 選擇器來選擇任何 HTML 元素節點。

延遲指令碼的載入 載入 JavaScript 檔案是一項昂貴的操作。瀏覽器必須下載檔案,解析內容,然後將其轉換為機器程式碼並執行。

瀏覽器下載一個檔案,同時會阻止其他任何操作。

因此,我們應該儘可能地延遲它。我們可以通過將 script 標記放在末尾來實現。另外,我們可以在 script 標籤上使用 defer 屬性來執行此操作。

另外,我們可以在頁面載入後通過動態建立 script 元素並按如下所示執行指令碼:

window.onload = () => {
  const element = document.createElement("script");
  element.src = "https://code.jquery.com/jquery-1.12.4.min.js";
  document.body.appendChild(element);
};
複製程式碼

頁面載入後,想載入任何內容都可以使用此指令碼的載入方法。

小結

我們可以通過做一些事情來加快頁面速度。首先,我們可以將資料快取在變數中,因此我們不必重複訪問它們。然後,我們可以使用 for 迴圈更快地遍歷專案。

另外,我們可以減小 DOM 大小以減少需要載入的專案。我們還可以通過將 DOM 物件分配給變數來在其程式碼中快取它們。

我們也不應宣告不必要的變數,並且應儘可能推遲指令碼的載入,以免卡住我們的瀏覽器。

相關文章