Вопрос по performance, javascript, jquery – Какова стоимость «$ (это)»?

56

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

<code>$('#container input').each(function() {
    $(this).addClass('fooClass');
    $(this).attr('data-bar', "bar");
    $(this).css('background-color', 'red');
});
</code>
Does caching the jQuery object really improve the performance of our code? What happens "behind the scenes" when you pass a DOM element to the jQuery constructor?
Вы должны всегда кэшировать, но в этом конкретном примере вам даже не нужно это делать. Просто воспользуйтесь преимуществами цепочки jQuery:$(this).addClass('fooClass').attr('data-bar', "bar").css('background-color', 'red'); Jose Rui Santos

Ваш Ответ

4   ответа
52

метка информация появляется это предупреждение:

Функция 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 имеет лишь небольшой эффект:

В Chrome он всего на 7% медленнее. (В IE это немного важнее: 12%.)

В любом случае вы сохраняете хотя бы один вызов функции каждый раз. Christoph
Сравнение неверное ... Производительность сильно отличается. Adi Darachi
14

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

// Handle $(DOMElement)
if ( selector.nodeType ) {
    this.context = this[0] = selector;
    this.length = 1;
    return this;
}
Вот хорошее приложение для просмотра источника: James.padolsey.com / JQuery / # v = мерзавец & п = jQuery.fn.init Joe
Теперь у селектора строк будет совершенно другой график. Joe
@ JoeTuskan. Я уточнил ваш комментарий в своем обновленном ответе. gdoron
Спасибо за то, что указал мне на источник jQuery. Я не знаю, почему я сам этого не сделал. gdoron
10

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

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

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

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

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

Хорошее объяснение !!! + 1 Gaurav123
Это сравнение намного лучше, чем сравнение принятого ответа. Adi Darachi
8

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

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

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

Рассмотреть возможность

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

инимизированный вывод @Closure компилятора

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

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

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

+ 1, хотя это скорее ответ на вопрос, почему вы должны кэшироватьthis не$(this) потому что вы можете получить тот же результат сthis.value; this.tagName; this.className; this.nodeType; this.... gdoron
@ gdoron, есть большая разница между использованием сырых методов DOM и jQuery; они не всегда взаимозаменяемы. addClass, data, анимация ...) Кроме того, между @ все еще есть разница в 3 байта на вызvar a = $(this); a...; a...; а такжеvar a = this; $(a)...; $(a)...; josh3736
Если вы распаковываете файлы, вы часто обнаруживаете, что в результате такого кэширования размер файла немного больше. В вашем примере разница составляет всего несколько байтов, 111 против 115 байтов, но это подчеркивает суть. Я понятия не имею, почему это так, но я часто обнаруживаю, что это так. cliffs of insanity
@ user1370958, сжатые файлы все еще меньше, просто меньше экономии. В двух приведенных выше примерах экономия от минимизации составляет 20% и 37%; минимизированная + сжатая экономия составляет 7% и 12%. Пока gzipped контентможе больше, чем исходный контент, обычно это происходит только для очень маленьких файлов (<50 байт). josh3736
Да, я просто имел в виду, что если ты копируешь, то кешируешь такие вещи, какthis может привести к большему файлу по сравнению с gzip-версией кода с некэшированнымthis. Они оба, безусловно, приведут к меньшему файлу, чем оригинал. Важно не процент сохраненного процента, поскольку исходные точки различны, а конечный размер файла в байтах - это то, что нужно измерять. cliffs of insanity

Похожие вопросы