Лучшие практики 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
, map
и filter
. А также цикл while
.
Из всех способов цикл for
является самым быстрым, с кэшированием length
или без него, как мы делали выше. Кэширование length
иногда делает цикл лучше, однако, некоторые браузерные движки оптимизировали цикл for
без кэширования свойства длины.
Цикл while
с декрементом индекса примерно в 1,5 раза медленнее, чем for
Использование forEach
в 10 раз медленнее, чем цикл for
, поэтому лучше его избегать, особенно для больших массивов.
Мы можем увидеть результаты здесь.
Уменьшить доступ DOM
Доступ к DOM - это дорогостоящая операция, поскольку браузер должен получить элемент с веб-страницы, а затем создать из него объект и вернуть его.
Чтобы уменьшить доступ к DOM, мы должны установить для объектов DOM Node переменную, если нам нужно манипулировать ею более одного раза.
Например, если у нас есть следующий HTML-код, и мы хотим задать ему текст через несколько секунд:
Мы можем написать следующий код для этого:
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 поиск для элементов с методами querySelector
, getElementById
или getElementsByTagName
будет быстрее, так как им придётся меньше искать.
Кроме того, производительность рендеринга страниц улучшится, так как загружается меньше контента. Это особенно верно для медленных устройств, таких как телефоны и планшеты.
Не объявляйте ненужные переменные
Каждый раз, когда мы объявляем переменные, браузер должен резервировать пространство памяти для переменных. Поэтому, чтобы уменьшить использование памяти, мы должны объявлять как можно меньше переменных.
Например, если у нас есть следующий HTML:
И мы хотим установить текстовое содержимое элемента 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
в конец нашего HTML документа. Также мы можем использовать атрибут 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 в нашем коде, назначая их переменным.
Мы также не должны объявлять ненужные переменные, и мы должны максимально откладывать загрузку скриптов, чтобы наш браузер показывал содержимое страницы как можно скорее.