Какова стоимость "$ (этого)"?

Люди здесь часто предлагают кэшировать объект jQuery, созданный из элемента DOM, например, с помощью этого кода:

$('#container input').each(function() {
    $(this).addClass('fooClass');
    $(this).attr('data-bar', "bar");
    $(this).css('background-color', 'red');
});
  • Ли кеширование объекта jQuery действительно повышает производительность нашего кода?
  • Что происходит "за кадром", когда вы передаете элемент DOM в конструктор jQuery?

Ответ 1

В информации тега jQuery появляется следующее предупреждение:

Функция jQuery $() стоит дорого. Повторное обращение к нему крайне неэффективно.

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

quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/

Затем, если строка является селектором (кроме id), jQuery обходит DOM, чтобы найти совпадение с его дорогой функцией find:

} else if ( !context || context.jquery ) {
    return ( context || rootjQuery ).find( selector );
}

Итак, да, это дорого, но это верно только для селекторов!

Если мы передаем DOMElement, единственным действием jQuery является сохранение параметра DOMElement в качестве контекста только что созданного объекта jQuery и установка длины контекста в 1:

// Handle $(DOMElement)
if ( selector.nodeType ) {
    this.context = this[0] = selector; // Selector here is a DOMElement
    this.length = 1;
    return this;
}

Я сделал несколько тестов с jsPerf, и я обнаружил, что кеширование объекта jQuery имеет лишь небольшой эффект:

Bar chart, described below

В Chrome он только на 7% медленнее. (В IE это немного более значимо: 12%.)

Ответ 2

Чтобы ответить на второй вопрос, посмотрите источник:

// Handle $(DOMElement)
if ( selector.nodeType ) {
    this.context = this[0] = selector;
    this.length = 1;
    return this;
}

Ответ 3

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

http://jsperf.com/this-cost/2

enter image description here

В более реальном мире относительная разница незначительна, так как ваш тест показал

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

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

Ответ 4

Одна вещь, которую испытывают все тесты производительности во время выполнения, является еще одним важным соображением:

Полоса пропускания сети.

Кэширование $(this) в локальную переменную, как правило, уменьшает размер вашего script, особенно при минировании (поскольку this не может быть уменьшено с четырех символов).

Рассмотрим:

function hello(text) {
    $(this).attr();
    $(this).css();
    $(this).data();
    $(this).click();
    $(this).mouseover();
    $(this).mouseleave();
    $(this).html(text);
}
hello('Hello world');

Закрытый выходной файл компилятора

function hello(a){$(this).attr();$(this).css();$(this).data();$(this).click();$(this).mouseover();$(this).mouseleave();$(this).html(a)}hello("Hello world");

Это экономит 39 байт (20%). Теперь рассмотрим:

function hello(name) {
    var $this = $(this);
    $this.attr();
    $this.css();
    $this.data();
    $this.click();
    $this.mouseover();
    $this.mouseleave();
    $this.html(name);
}
hello('Hello world');

Минифицированный выход

function hello(b){var a=$(this);a.attr();a.css();a.data();a.click();a.mouseover();a.mouseleave();a.html(b)}hello("Hello world");

Это экономит 74 байта (37%), что почти удваивает наши байтовые сбережения. Очевидно, что реальные сбережения в больших сценариях будут ниже, но вы по-прежнему можете значительно уменьшить размер вашего script путем кэширования.

Действительно, есть только потенциал для кеширования $(this). Вы получаете минимальное, но измеримое увеличение производительности во время выполнения. Что еще более важно, вы можете уменьшить количество байтов, которые перемещаются по проводу, и , что напрямую переводит на большее количество долларов, потому что более высокая загрузка страницы равна больше продаж.

Если вы посмотрите на это таким образом, вы можете сказать, что количественная стоимость доллара повторяется $(this) и не кэширует ее.