JavaScript

Ограничение доступа к переменным и свойствам

Задача состоит в том, чтобы сократить время доступа к переменным и свойствам объектов в приложениях.

Причина заключается в том, что при каждом обращении процессору необходимо получить доступ к элементу в памяти, чтобы вычислить его результаты. Следовательно, это действие нужно выполнять как можно реже.

Например, при наличии цикла не нужно писать следующее:

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 также проходят по массиву после выполнения операций map и filter. Также есть цикл while.

Из всех способов запуска циклов for является самым быстрым как с, так и без кэширования length. Однако в некоторых случаях оно повышает эффективность.

Некоторые движки браузеров оптимизировали цикл for без кэширования свойства length.

Цикл while с уменьшающимся индексом примерно в 1,5 раза медленнее цикла for.

Цикл forEach в 10 раз медленнее for, поэтому лучше избегать его использования, особенно для больших массивов.

Результаты можно посмотреть здесь.

Ограничение доступа к 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 возвращает промис об установке текста для данного элемента через 3 секунды.

Также у нас есть функция async для установки текста 3 раза. Важный момент: ссылка на элемент передается при каждом вызове. Таким образом, мы избавляемся от необходимости получать элемент с веб-страницы 3 раза, что является дорогостоящей операцией.

Уменьшение размера DOM

Рендеринг дерева DOM — это медленный процесс. Следовательно, необходимо уменьшить размер дерева. Единственный способ — максимально упростить веб-страницы.

Уменьшение размера DOM ускоряет поиск элементов с помощью таких методов, как querySelectorgetElementById или 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, а также связанный метод querySelectorAll, для выбора элементов, поскольку они оба применяют CSS-селекторы для выбора любого узла элемента HTML.

Отложенная загрузка сценариев

Загрузка файлов JavaScript — дорогостоящая операция. Браузер должен загрузить файл, проанализировать содержимое, а затем преобразовать его в машинный код и запустить.

Браузер загружает один файл построчно, не допуская выполнения других операций. Следовательно, нам нужно отложить эту операцию. Для этого разместите тег script в конце кода. Также можно использовать атрибут defer тега script. Кроме того, сценарии можно запускать после загрузки страницы, создавая элементы 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 в коде, присваивая их переменным.

И, наконец, избегайте объявления ненужных переменных и откладывайте загрузку сценариев, чтобы не задерживать работу браузера.

Читайте также:


Перевод статьи John Au-Yeung: JavaScript Best Practices — Performance