Статьи

Как начинающие jQuery могут тестировать и улучшать свой код

Прибытие jQuery сделало процесс написания JavaScript смехотворно простым. Но вы заметите, что небольшие изменения в вашем коде значительно улучшают читабельность и / или производительность. Вот несколько советов, которые помогут вам оптимизировать код.


Нам понадобится надежная платформа для проведения наших тестов. Вот HTML-разметка для тестовой страницы, на которой мы будем запускать все наши тесты:

Здесь нет ничего особенного; просто набор элементов, на которые мы можем ориентироваться и тестировать. Мы используем Firebug для регистрации времени здесь. Профиль начинает процесс, а profileEnd останавливает его и записывает , сколько времени заняло задание. Я обычно использую метод основного профиля Firebug, но для наших коварных целей этого будет достаточно.


Как это часто бывает, вы будете обслуживать один файл сценария, содержащий ваш код, для всех страниц вашего сайта. Обычно это код, который часто выполняет действия с несуществующими элементами на текущей странице. Хотя jQuery изящно решает такие проблемы, это не значит, что вы можете просто игнорировать любые проблемы. Фактически, если вы вызываете методы jQuery для пустой коллекции, они не будут запущены.

Рекомендуется только запускать код, который применим к загруженной в данный момент странице, вместо того, чтобы объединять весь код в единый документ, готовый к проверке, и передавать его клиенту.

Давайте посмотрим на первый сценарий:

1
2
3
4
5
6
7
console.profile();
var ele = $(«#somethingThatisNotHere»);
ele.text(«Some text»).slideUp(300).addClass(«editing»);
$(«#mainItem»);
console.profileEnd();
     
//Some more awesome, ground shattering code here ._.

Firebug’s выплевывает следующий результат:

Учебное изображение

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

И результаты:

Учебное изображение

Видеть? Это довольно просто, к сути и выполняет свою работу. Обратите внимание, что вам не нужно проверять, существует ли элемент для каждого бита вашего кода . Вы заметите на своей странице, что некоторые большие части, как правило, выиграют от этого метода. Используйте свое суждение здесь.


Попробуйте использовать идентификатор вместо прохождения класса.

Это большая тема, поэтому я буду держать ее как можно более краткой. Прежде всего, при передаче селекторов, попробуйте использовать идентификатор вместо передачи класса. jQuery напрямую использует нативный метод getElementById для поиска элемента по ID, в то время как в случае с классом ему нужно выполнить внутреннее вуду, чтобы получить его, по крайней мере, в старых браузерах.

Мы рассмотрим различные селекторы, которые вы можете использовать для нацеливания на 2-й элемент li . Мы проверим каждый из них и как они изменяют производительность.

Первый способ, самый простой, состоит в том, чтобы явно нацелить его, используя выбранный класс. Давайте посмотрим, что возвращает профайлер Firebug.

Учебное изображение

И результат: 0.308мс. Далее мы добавляем префикс имени тега, чтобы сузить его. Таким образом, мы можем сузить наш поиск, сначала нацеливаясь только на выбранные элементы DOM, используя document.getElementsByTagName.

Учебное изображение

И результат: 0,291мс. Примерно 0,02 мс сбрили. Это незначительно из-за того, что мы тестируем в Firefox; однако следует отметить, что это повышение производительности будет заметно выше в старых браузерах, таких как Internet Explorer 6.

Далее мы спускаемся с идентификатора родительского элемента.

Учебное изображение

И результат: 0,283мс. Давайте попробуем быть более конкретным. Мы также указываем тип элемента в дополнение к идентификатору предка.

Учебное изображение

И результат: 0,275 мс. Еще одна небольшая часть выбрита. Наконец, давайте просто нацелить его напрямую, используя идентификатор для.

Учебное изображение

И результат: 0,165мс. Впечатляет! Это действительно показывает, насколько быстрее запускать нативные методы. Обратите внимание, что хотя современные браузеры могут использовать преимущества таких вещей, как getElementsByClassName, старые браузеры не могут — что приводит к гораздо меньшей производительности. Всегда учитывайте это при кодировании.


Sizzle, механизм выбора, который использует jQuery — созданный Джоном Резигом — анализирует селекторы справа налево, что вызывает несколько неожиданных цепочек разбора.

Рассмотрим этот селектор:

Когда Sizzle встречает такой селектор, он сначала строит структуру DOM, используя селектор в качестве корня, отбрасывает элементы, которые не имеют требуемого класса, и для каждого элемента с классом он проверяет, имеет ли его родительский идентификатор ID someList .

Чтобы учесть это, убедитесь, что самая правая часть вашего селектора настолько конкретна, насколько это возможно. Например, указав li.selected вместо .selected , вы сокращаете количество проверяемых узлов. Это причина, почему производительность подскочила в предыдущем разделе. Добавляя дополнительные ограничения, вы эффективно сокращаете количество проверяемых узлов.

Чтобы лучше настроить способ получения элементов, вам нужно добавить контекст для каждого запроса.

1
2
var someList = $(‘#someList’)[0];
$(«.selected», someList);

При добавлении контекста способ поиска элемента полностью меняется. Теперь выполняется поиск элемента, предоставляющего контекст — в нашем случае someList , и после его получения дочерние элементы, не имеющие требуемого класса, удаляются.

Обратите внимание, что обычно рекомендуется передавать элемент DOM в качестве контекста вашего селектора jQuery. Использование контекста наиболее полезно, когда оно хранится в некоторой переменной. В противном случае вы можете упростить процесс и использовать find () — что jQuery сам делает под капотом.

1
$(‘#someList’).find(‘.selected’);

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


Когда вы просматриваете чужой код, вы часто находите.

Пожалуйста, не делай этого. Когда-либо. Разработчик создает этот «элемент» снова и снова. Это расточительно.

Посмотрим, сколько времени потребуется для запуска такого ужасного кода.

Учебное изображение

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

1
2
3
4
5
console.profile();
  
$(«#mainItem»).hide().val(«Hello»).html(«Oh, hey there!»).show();
  
console.profileEnd();

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

Но если, в отличие от вышеизложенного, разделы, ссылающиеся на элемент, не являются параллельными, вам придется кэшировать элемент, а затем выполнять все те же операции, что и раньше.

Учебное изображение

Как видно из результатов, кэширование или создание цепочек значительно сокращают время выполнения.


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

Для теста мы создадим 50 элементов li , добавим их в текущий список и определим, сколько времени это займет.

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

Посмотрим как получилось, ладно?

Учебное изображение

Теперь мы пойдем по несколько иному пути. По сути, мы добавим требуемую строку HTML в переменную firs, а затем перезапустим DOM только один раз.

Учебное изображение

Как и ожидалось, время, затраченное на это, значительно сократилось.

Учебное изображение

Если вы используете jQuery в качестве замены для getElementById, но никогда не используете ни один из предоставленных им методов, то вы делаете это неправильно.

Если вы хотите пойти дальше, спросите себя, действительно ли вам нужно создать новый объект jQuery для цели какого-то элемента? Если вы используете jQuery в качестве замены для document.getElementById, но никогда не используете ни один из предоставленных им методов, то вы делаете это неправильно. В этом случае мы можем сойти с рук с сырым JS.


Вы заметите, что разница во времени выполнения между оптимизированным и неоптимизированным кодом составляет доли миллисекунды. Это потому, что наш тестовый документ очень маленький с невероятно небольшим количеством узлов. Как только вы начнете работать с сайтами производственного уровня с несколькими тысячами узлов, это действительно сложится.

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

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

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


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

Вопросов? Хорошие вещи, чтобы сказать? Критицизмы? Нажмите на раздел комментариев и оставьте мне комментарий. Удачного кодирования!