Страницы

Поиск по вопросам

понедельник, 12 ноября 2018 г.

Обоснование необходимости повторного вызова функции jQuery, когда объект уже создан

Допустим, мы хотим повесить обработчик события на кнопку
var messagesBtn = $("#menu_btn-messages");
В переменную messagesBtn у нас уже записан объект jQuery, и по идее теперь мы можем вызывать методы этого обекта:
messagesBtn.on('click', function(){ ... });
Тем не менее, насколько я видел в примерах, пишут:
$(messagesBtn).on('click', function(){ ... });
Получается, мы рекурсивно вызываем $($("#menu_btn-messages")). Прокомментируйте, пожалуйста, это явление.


Ответ

Когда вы пишете var messagesBtn = $("#menu_btn-messages"), вы записываете результат выполнения функции $() в переменную messagesBtn. В этой переменной хранится состояние элемента на момент присваивания переменной. Зачем так делают? Ну, на то есть как минимум 2 причины.
Первая и главная причина - это оптимизация. Такой процесс, кажется, называется кэшированием селекторов, но я могу ошибаться. Короче говоря, при каждом вызове функции $() происходят какие-то вычисления, которые тратят ресурсы (поиск элемента, построение jQuery-объекта и т.п.). Чтобы эти ресурсы лишний раз не тратить, объекты jQuery (и не только их - с обычными элементами DOM на ванильном JavaScript делают то же самое) часто помещают в переменные. Вот два теста:
Первый:
var iterations = 1000000; console.time('Function #1'); for (var i = 0; i < iterations; i++) { $('body').attr('title', 'test'); $('body').attr('title', 'foo'); $('body').attr('title', 'baz'); } console.timeEnd('Function #1');
Второй:
var iterations = 1000000; console.time('Function #1'); for (var i = 0; i < iterations; i++) { var $body = $('body'); $body.attr('title', 'test'); $body.attr('title', 'foo'); $body.attr('title', 'baz'); } console.timeEnd('Function #1');
Лично у меня первый тест выполнялся медленнее второго в 2 раза на Chrome 55.0.2883.87 m (64-bit) для Windows 10.
На самом деле, подобное кэширование не очень-то и сильно влияет на производительность в реальных условиях. Разница в скорости, конечно, в 2 раза, но обычный вызов функции $() выполняется слишком быстро, и если во всем сценарии у вас парочка вызовов, то разницу вы не заметите. Но кэширование нужно использовать, если вы работаете с jQuery из событий, которые выполняются невероятно часто. Например, событие скролла или событие ресайза окна браузера. Было бы неплохо приучить себя постоянно писать с использованием переменных.
Вторая причина, почему так делают - это читаемость кода и удобство его поддержки. Для лучшей читаемости рекомендуется переменные, содержащие jQuery-объект, именовать с символом доллара в начале (чтобы обозначить, что в переменной находится jQuery-объект), как во втором тесте, и давать имя, основанное не на имени класса или ID, а на значении (назначении) элемента. Таким образом, вы можете изменить имя селектора лишь в одном месте и не бояться, что вы где-то что-то забыли.
Что происходит, когда вы передаете jQuery-объект в функцию $(), например $($("#menu_btn-messages"))? Да ничего интересного и необычного. Разработчики jQuery таким образом лишь предотвратили возможные путаницы в коде. Но так делать не рекомендуется - это лишняя трата ресурсов.

Комментариев нет:

Отправить комментарий