Прокачиваем навыки отладки с помощью инструментов разработчика Chrome (часть 2)

Перевод статьи Improve Your Debugging Skills with Chrome DevTools (Part 2) с сайта telerik.com для css-live.ru, автор — Питер Милчев

Chrome devtools

В этой статье мы рассмотрим продвинутые функции отладчика Chrome, закрепив навыки, полученные в первой части.

Вы научились проверять сгенерированный HTML и применённые стили? Уже смело можете отлаживать JavaScript в браузере? Надеюсь, поскольку в этой серии мы рассмотрим продвинутые функции отладчика Chrome, закрепив навыки, полученные в первой части.

Освоив новые навыки, мы поэкспериментируем с базовыми примерами Kendo UI, а в конце статьи возьмём реальный пример jQuery Grid, чтобы отточить на нем свежеприобретенные знания.

В этой статье:

Умное автодополнение

Умное автодополнение — известная функция в IDE, помогающая эффективнее писать код. В Chrome 68 разработчики DevTools включили аналогичные функции в консоль. А именно: упреждающее вычисление, автодополнение после выполнения функции и подсказки для аргументов.

Давайте рассмотрим эти возможности на примере следующей функции:

function test(yourValue) { return { value: yourValue, multiplied: yourValue * 3 };
}

Упреждающее вычисление

Вот что отобразится в консоли отладчика Chrome с включённым упреждающим вычислением:

Упреждающее вычисление

Таким образом можно вычислять выражения в коде в консоли, если у этих выражений нет побочных эффектов (когда выполнение кода не только возвращает значение, но и делает ещё что-то). Подробнее о побочных эффектах можно узнать из вопроса «JavaScript-замыкания и побочные эффекты простым языком?» на StackOverflow

Совет: такое же вычисление происходит, когда вы открываете вкладку «Исходники» (Source) в режиме отладки и наводите на выражение или выделяете его.

Автодополнение после выполнения функции

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

Совет: сохраните результат функции в переменной (см. «Автодополнение IntelliSense для объектов на стороне клиента») и для проверки результата выполните функцию в консоли.

Затем используйте API консоли и сохраните выражение в переменной как var lastEvaluatedExpression = $_;.

Подсказки для аргументов

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

Лёгкое обращение к выбранным элементам и выполненным выражениям

В предыдущем разделе я не пояснил, что делает переменная $_. Это не магия, а часть встроенного API командной строки. Отладчик Chrome присваивает объекты и выражения списку предопределенных переменных. Например, при вычислении выражения 40+2 получится 42. И, допустим, мне лень запоминать, как называлась переменная или что это было за выражение, а тем более ждать 7.5 миллионов лет, пока компьютер высчитывает этот ответ. С отладчиком Chrome теперь достаточно переменной $_.

API командной строки в отладчике Chrome сохраняет объекты и результаты выражения в предопределённые переменные. Консоль предоставляет ещё и такие полезные сокращения: $0, $1, $2, $3 и $4. $0 ссылается на последний выбранный элемент в панели «Элементы», $1 — на предыдущий, и так далее. Это может оказаться полезным, когда нужно получить ссылку на DOM-элемент, предоставляющий компонент или виджет, и вам нужно быстро проверить его доступные части.

Давайте поупражняемся с этим на примере PanelBar для Kendo UI, где мы обратимся к первому элементу, скроем его, а после покажем снова.

Лёгкое обращение к выбранным элементам и выполненным выражениям

Совет: отладчик Chrome может подсказать вам, как оптимизировать изменения HTML и DOM, которые происходят в вашем приложении (см. «Молниеносное отображение списка в Angular»)

Просматривать всплывающие подсказки бывает нелегко, поскольку они исчезают через какое-то время. С другими автоматически скрываемыми элементами — вроде тех, что отображаются при взаимодействии с юзером (к примеру, клик мышью или перетаскивание) — та же история. Чтобы их отловить, я часто прибегал ко всяким ухищрениям, придумывая жуткий код, который будет на них ссылаться. Встречайте setTimeout() и debugger.

setTimeout() нужен для выполнения определённой логики через заданное время. А ещё он меняет порядок выполнения функций. Это пригодится при выполнении функции после быстрой анимации (см. «Почему setTimeout(fn, 0) иногда полезен?»)

Разобравшись, как работает setTimeout(), мы можем объединить его мощь с оператором debugger, и тогда можно будет активировать режим отладки, когда автоматически скрываемый элемент виден, и не бояться, что он тотчас же исчезнет.

На анимации ниже показано, как можно просмотреть всплывающую подсказку, вызывая setTimeout(function(){debugger; }, 3000) в консоли:

Лёгкое обращение к выбранным элементам и выполненным выражениям

На иллюстрации выше представлены API рисования и виджет jQuery Tooltip из Kendo UI

Совет: чтобы вывести в лог элементы, на которые в данный момент перешёл фокус, вставьте следующий код консоль: window.focusedelement; setInterval(function(){ if(window.focusedElement != document.activeElement){window.focusedElement = document.activeElement; console.log(document.activeElement)}})

Для отмены повторения с интервалом можно перезагрузить страницу или использовать clearInterval():

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

Точки останова по изменению DOM

Они прерывают выполнение скрипта, если у выбранного элемента в DOM меняется структура, атрибут или он удаляется с помощью JavaScript. Чтобы включить/выключить эту возможность, кликните правой кнопкой по элементу в панели «Элементы», наведите на пункт «Остановить» (Break) в контекстном меню и выберете «модификации поддерева» (subtree modifications), «модификации атрибута» (attribute modifications) или «удаление узла» (node removal).

Лёгкое обращение к выбранным элементам и выполненным выражениям

Точки остановка для XHR/Fetch

Они прерывают выполнение скрипта, если адрес запрошенного ресурса содержит строку, на которую настроена точка останова. Чтобы включить/выключить эту возможность: разверните область «Точки останова для XHR» (XHR Breakpoints) в панели «Исходники», кликните на кнопку «Добавить точку останова» (Add breakpoint) и введите нужную часть URL.

Лёгкое обращение к выбранным элементам и выполненным выражениям

Точки останова для обработчиков событий

Они прерывают выполнение скрипта при срабатывании событий мыши, клавиатуры, устройства, анимации и так далее. Чтобы включить/выключить эту возможность: разверните область «Точки останова для обработчиков событий» (Event Listeners Breakpoints) во вкладке «Исходники» и отметьте нужные (категории) события.

Лёгкое обращение к выбранным элементам и выполненным выражениям

Точки останова для исключений

Они прерывают выполнение скрипта, когда выбрасываются обработанные или необработанные исключения. Чтобы включить/выключить эту возможность: нажмите кнопку «Пауза при исключении» (Pause on Exception) во вкладке «Исходники»; когда эта кнопка включена, появляется добавочная опция «Пауза при обработанных исключениях» (Pause on caught exceptions).

Лёгкое обращение к выбранным элементам и выполненным выражениям

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

  • Нажмите на кнопку «Продолжить» (Continue), чтобы показать раскрывающийся список и выберите кнопку «Продолжить без прерывания» (Continue without interruption).
  • Нажмите F12, чтобы быстро закрыть отладчик Chrome.

Во вкладке «Исходники» стоит упомянуть еще несколько областей.

  • Вкладка «Выражения для отслеживания» (Watch expressions): позволяет отслеживать значения переменных и выражений в разные моменты времени.
  • Раздел «Стек вызовов» (Call Stack) показывает путь выполнения, который привёл код к этой точке останова в обратном хронологическом порядке.
  • Панель «Область видимости» (Scope): показывает, какие локальные и глобальные переменные определены в данный момент.

Контексты выполнения в отладчике Chrome

Вы когда-нибудь сталкивались с ошибкой ReferenceError (говорящей, что функция не определена) при попытке выполнить уже объявленную функцию в консоли браузера? Вы не одиноки, это частый случай.

К примеру, такую ошибку можно поймать, когда страница со скриптом загружаеся в <iframe>, поэтому находится в другом контексте выполнения. Вкратце, контекст выполнения похож на область видимости, и у каждой страницы, <iframe> или расширения браузера есть свой контекст выполнения. Между разными контекстами можно переключаться с помощью раскрывающегося списка в консоли:

contexts-in-dojo.png

Немного соображений насчёт контекста выполнения:

  • Когда вы просматриваете какой-либо элемент, в качестве контекста выполнения автоматически выбирается страница, содержащая этот элемент
  • Чтобы получить логи из всех контекстов в консоли, уберите галочку «Только выбранный контекст» (Selected context only) в настройках консоли.
  • С правой стороны есть ссылка на файл, выполнивший функцию, которая отвечает за запись в логе.

Эти контексты хорошо видны в «песочнице» по Kendo UI, в которой мы сейчас потестируем вышеприведенные советы.

contexts-in-dojo.png

Пример: компонент jQuery Grid из Kendo UI

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

Задача: используйте JavaScript для изменения фона плавающего элемента, созданного при перетаскивании заголовка в этом примере из «песочницы» на основе демо компонента jQuery Grid из Kendo UI.

Пробуйте сделать это сами, но если не выйдет, воспользуйтесь следующими советами:

К этому моменту вы должны быть уже на «ты» с отладчиком Chrome — никакая магия CLI, автоматически скрывающиеся элементы или сложные сценарии отладки не могут помешать вам. Мы здорово овладели всем этим и одолели тёмную сторону. Кроме шуток, надеюсь, что эта статья была полезной и ответила хотя бы на один сложный вопрос — дайте знать. А что насчёт ваших советов и приёмов? Пожалуйста, поделитесь ими (потому что вам не всё равно) в комментариях ниже.

P.S. Это тоже может быть интересно: