В финальной ветке jQuery 3.x есть методы, которые в современном браузере работают значительно медленнее нативных аналогов.
Ниже приведены категории методов и подходов в jQuery 3.x, которые сильнее всего бьют по производительности, и то, на что их стоит заменить.
1. Циклические переборы: $.each() и $().each()
Это главный враг производительности при обработке массивов или больших коллекций DOM-элементов.
- В чем проблема:
$.each()создает новую область видимости и функцию-колбэк для каждой итерации. На массиве из 10 000 элементов нативный цикл выполнится за микросекунды, а jQuery-метод вызовет функцию 10 000 раз, создавая колоссальную нагрузку на память. - Плохо:
$.each(largeArray, function(index, value) { ... }); - Как эффективно: Используйте классический цикл
forили встроенный нативный методarray.forEach().
2. Псевдо-селекторы (Sizzle Engine): :visible, :hidden, :animated, :has()
Селекторы, которые начинаются с двоеточия (кроме базовых CSS вроде :focus), не поддерживаются стандартным браузерным движком querySelectorAll().
- В чем проблема: Когда вы пишете
$('.item:visible'), jQuery не может отдать эту строку браузеру. Он вынужден сначала найти вообще все элементы.item, запустить внутренний тяжелый движок Sizzle, поштучно проверить геометрические свойства каждого элемента (высоту, ширину, opacity) и только потом вернуть результат. - Плохо:
$('.item:visible').addClass('active'); - Как эффективно: Сначала найдите элементы стандартным селектором, а затем отфильтруйте их с помощью нативного метода или более легких функций:
$('.item').filter(':visible').addClass('active'); // Быстрее, так как Sizzle работает только с отфильтрованной выборкой
3. Метод .html(value) (в цикле)
Используется для вставки HTML-кода внутрь элементов.
- В чем проблема: Каждый раз, когда вызывается
.html(), jQuery парсит переданную строку, уничтожает старые обработчики событий внутри элемента (чтобы избежать утечек памяти) и перестраивает DOM-дерево. Если делать это поштучно в цикле, интерфейс начнет «заикаться». - Плохо:
// 100 тяжелых обращений к DOM for(let i=0; i<100; i++) { $('#list').append('<li>' + i + '</li>'); } - Как эффективно: Сформируйте одну большую строку или массив в оперативной памяти и обновите DOM всего один раз:
let html = ''; for(let i=0; i<100; i++) { html += '<li>' + i + '</li>'; } $('#list').html(html); // Один вызов
4. Повторяющиеся базовые методы без кэширования
Строго говоря, это беда производительности самого jQuery-обертывания ($()).
- В чем проблема: Каждый вызов функции
$('#my-el')заставляет jQuery заново искать этот элемент в DOM-дереве документа и создавать в памяти под него новый экземпляр JS-объекта со всеми методами библиотеки. - Плохо:
$('#my-el').css('color', 'red'); $('#my-el').attr('data-status', 'ready'); $('#my-el').show(); - Как эффективно: Кэшируйте выборку в переменную или используйте чейнинг (цепочки методов) — это исключит повторный поиск элемента:
// Чейнинг (быстрее) $('#my-el').css('color', 'red').attr('data-status', 'ready').show(); // Либо сохранение в переменную (идеально для частых вызовов) const $el = $('#my-el'); $el.css('color', 'red');
5. Поштучное навешивание событий вместо делегирования
- В чем проблема: Если у вас есть таблица на 500 строк, и вы вешаете клик на класс строки через
$('.row').click(...), jQuery создаст в памяти 500 независимых слушателей событий. - Плохо:
$('.dynamic-button').click(function() { ... }); - Как эффективно: Используйте делегирование событий через метод
.on(). Событие вешается только на одного родителя (например, на саму таблицу илиdocument), а jQuery просто отлавливает всплывающие клики. Это экономит кучу памяти.\$(document).on('click', '.dynamic-button', function() { ... });