Несколько советов по оптимизации производительности JavaScript

внешний интерфейс JavaScript
Несколько советов по оптимизации производительности JavaScript

Этот перевод Джона Ау-Юнга изЛучшие практики JavaScript - производительность

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

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

Уменьшить доступ к переменным и атрибутам

Мы должны уменьшить количество обращений к переменным и свойствам объектов в нашем приложении.

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

Поэтому мы должны сделать это как можно меньше.

Например, для цикла это не должно выглядеть так:

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. Операции отображения и фильтрации также проходят через массивы. Также есть цикл while.

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

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

Цикл 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 секунды.

Затем у нас есть асинхронная функция для установки текста 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 в конец. В качестве альтернативы мы можем использовать для этого атрибут 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, чтобы кэшировать их в своем коде.

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