Подробный гайд по отладке кода на JavaScript в Chrome Devtools. Современная отладка JavaScript

Время от времени разработчики совершают ошибки при кодировании. Ошибка в программе или скрипте называется ошибкой.

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

Сообщения об ошибках в IE

Самый простой способ отслеживания ошибок - включить информацию об ошибках в вашем браузере. По умолчанию Internet Explorer показывает значок ошибки в строке состояния при возникновении ошибки на странице.

Двойной щелчок по этому значку приведет вас к диалоговому окну, отображающему информацию о конкретной ошибке.

Поскольку этот значок легко упускать из вида, Internet Explorer дает вам возможность автоматически отображать диалоговое окно «Ошибка» всякий раз, когда возникает ошибка.

Чтобы включить эту опцию, выберите « Инструменты» → « Свойства обозревателя» → вкладка «Дополнительно». а затем, наконец, установите флажок «Показать уведомление о каждом скрипте», как показано ниже -

Сообщения об ошибках в Firefox или Mozilla

Другие браузеры, такие как Firefox, Netscape и Mozilla, отправляют сообщения об ошибках в специальное окно, называемое Консоль JavaScript или Консоль ошибок. Чтобы просмотреть консоль, выберите « Инструменты» → « Консоль ошибок» или «Веб-разработка».

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

Уведомления об ошибках

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

Если вы используете Firefox, вы можете нажать на ошибку, доступную в консоли ошибок, чтобы перейти к точной строке в скрипте с ошибкой.

Как отлаживать скрипт

Существуют различные способы отладки вашего JavaScript - Использовать JavaScript Validator

Один из способов проверить код JavaScript для странных ошибок - запустить его через программу, которая проверяет ее, чтобы убедиться, что она действительна и что она соответствует официальным синтаксическим правилам языка. Эти программы называются синтаксическими анализаторами или просто валидаторами для краткости и часто идут с коммерческими редакторами HTML и JavaScript.

Наиболее удобным валидатором для JavaScript является JavaScript Lint Дугласа Крокфорда, который доступен бесплатно в JavaScript Lint Дугласа Крокфорда.

Просто зайдите на эту веб-страницу, вставьте код JavaScript (только JavaScript) в предоставленную текстовую область и нажмите кнопку jslint. Эта программа будет анализировать ваш код JavaScript, гарантируя, что все определения переменных и функций следуют правильному синтаксису. Он также будет проверять инструкции JavaScript, такие как if и while, чтобы они также соответствовали правильному формату

Добавить код отладки в ваши программы

Вы можете использовать методы alert() или document.write() в своей программе для отладки вашего кода. Например, вы можете написать что-то следующее:

var debugging = true; var whichImage = "widget"; if(debugging) alert("Calls swapImage() with argument: " + whichImage); var swapStatus = swapImage(whichImage); if(debugging) alert("Exits swapImage() with swapStatus=" + swapStatus);

Изучая содержимое и порядок alert() по мере их появления, вы можете легко проверить работоспособность своей программы.

Как использовать отладчик JavaScript

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

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

  • Используйте много комментариев. Комментарии позволяют вам объяснить, почему вы написали сценарий так, как вы это делали, и объяснить особенно сложные разделы кода.
  • Всегда используйте отступы, чтобы ваш код был легко читаемым. Отступы также облегчают вам сопоставление начальных и конечных тегов, фигурных скобок и других элементов HTML и скрипта.
  • Напишите модульный код. По возможности группируйте свои заявления в функции. Функции позволяют группировать связанные операторы, а также тестировать и повторно использовать части кода с минимальными усилиями.
  • Будьте последовательны в том, как вы называете свои переменные и функции. Попробуйте использовать имена, которые достаточно длинны, чтобы быть значимыми и описывать содержимое переменной или назначение функции.
  • Используйте согласованный синтаксис при именовании переменных и функций. Другими словами, держите их в нижнем регистре или в верхнем регистре; если вы предпочитаете нотацию Camel-Back, используйте ее последовательно.
  • Проверять длинные скрипты модульным способом. Другими словами, не пытайтесь написать весь скрипт перед тестированием любой его части. Напишите часть и запустите ее, прежде чем добавлять следующую часть кода.
  • Используйте описательные имена переменных и функций и избегайте использования односимвольных имен.
  • Следите за кавычками. Помните, что кавычки используются парами вокруг строк и что оба кавычки должны быть одного и того же стиля (одного или двух).
  • Следите за своими равными знаками. Вы не должны использовать один = для целей сравнения.
  • Явным образом объявляю переменные с помощью ключевого слова var.

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

  1. “Loading…” сообщение строки состояния не исчезает, когда приложение закончило загружаться.
  2. Язык по умолчанию - норвежский, даже в английских версиях IE и Firefox.
  3. Где то в коде образовалась глобальная переменная prop (зло - прим. пер.).
  4. В DOM-вьювере все элементы почему то имеют атрибут «clone».

Запуск отладчиков

  • В Firefox вы должны убедится, что у вам установлено расширение Firebug. Выберите “Инструменты > Firebug > Open Firebug”.
  • В Опере 9.5+, выберите “Инструменты > Дополнительно > Средства разработки.”
  • В бете IE, выберите “Сервис > Панели > Панели обозревателя > IE Developer Toolbar.”
  • В Safari или WebKit, сначала включите меню отладки (1) , затем выберите “Разработать > Показать веб-инспектор”
Пришло время запускать отладчики. Так как некоторые инструкции требуют изменения кода, вам лучше сохранить тестовую страницу и загрузить ее браузером с диска.

Ошибка № 1: Сообщение “Загрузка …”

Если вы посмотрите на отлаживаемое приложение, то сначала вы увидите то, что изображено на рисунке 1.


рис. 1: начальный вид нашего JavaScript-приложения в Dragonfly и Firebug, соответственно.

Когда вы смотрите на исходный текст в отладчике, обратите внимание на функцию clearLoadingMessage() в самом начале кода. Это неплохое место для контрольной точки.

Как её поставить:

  1. Щелкните мышью в левом поле на номере строки, чтобы установить контрольную точку на первой строке
  2. Перезагрузите страницу.
Обратите внимание: контрольная точка должна быть установлена на строке с кодом, который выполнится, когда функция будет запущена. Строка, которая содержит clearLoadingMessage(){ не подходит, так как является лишь определением функции. Если вы установите контрольную точку здесь, отладчик на ней не остановится, вместо этого контрольную точку надо устанавливать внутри функции.

Когда страница будет перезагружена, выполнение скрипта будет остановлено и вы увидите то, что показано на рисунке два.


рис. 2: отладчики остановились в контрольной точке внутри clearLoadingMessage.

Давайте взглянем на код функции. Как нетрудно заметить, в ней обновляются два DOM элемента, а в строке 31 упоминается слово statusbar. Похоже, что getElements("p", {"class":"statusbar"}).innerHTML ищет элемент statusbar в дереве DOM. Как бы нам быстро проверить своё предположение?

Вставьте эту инструкцию в командную строку, чтобы проверить. На рисунке три показаны три скриншота (Dragonfly, Firebug и IE8) после чтения innerHTML или outerHTML элемента, возвращенного командой, которую вы исследуете.

Чтобы проверить сделайте следующее:

  1. Найдите командную строку:
    * В Firebug, переключитесь в закладку “Console”.
    * В Dragonfly, просмотрите пониже панели кода JavaScript.
    * В IE8, найдите закладку справа «Console».
  2. Вставьте getElements("p", {"class":"statusbar"}).innerHTML в командную строку.
  3. Нажмите Enter.



рис. 3: вывод результата команды в Dragonfly, Firebug, и IE8, соответственно.

Командная строка - очень полезный инструмент, который позволяет вам быстро проверять маленькие куски кода. Интеграция консоли Firebug очень полезна - если Ваша команда выводит объект, вы получаете очень интеллектуальное представление. Например, если это объект DOM - вы увидите размеченный результат.

Можно использовать консоль, чтобы провести более глубокое исследование. Строка JavaScript, которую мы изучаем, делает следующие три вещи:

  1. Получает ссылку на элемент statusbar.
  2. Находит firstChild, другими словами, первый узел в этом параграфе.
  3. Устанавливает свойство innerText.
Давайте попробуем запустить в консоли, что-то большее, чем предыдущая команда. Например вы можете попробовать узнать, какое текущее значение у свойства innerText, перед тем как ему присваивается новое значние. Чтобы узнать это, вы можете напечатать всю команду до знака "=" в командную строку:
getElements("p" , {"class" :"statusbar" }).firstChild.innerText

Сюрприз, на выходе… ничего. Таким образом выражение getElements ("p", {"класс:"statusbar" "}) .firstChild указывает на какой то объекст в DOM, который не содержит никакого текста, или не имеет свойства innerText.

Тогда, следующий вопрос: что на самом деле является первым дочерним элементом у параграфа? Давайте зададим этот вопрос коммандной строке. (См. четвертый рисунок).

рис. 4: командная строка отладчика СтDragonfly, вывод [объект Text].

Вывод отладчика Dragonfly’s - [объект Text] показывает, что это - текстовый узел DOM. Таким образом мы нашли причину первой проблемы. У текстового узла нет свойства innerText, следовательно, установка значения для p.firstChild.innerText ничего не делает. Эта ошибка легко может быть исправлена, если заменить innerText на nodeValue, который является свойством, определенным стандартом W3C для текстовых узлов.

Теперь, после того как мы разобрались с первой ошибкой:

  1. Нажмите или кнопку Run, чтобы закончить скрипт.
  2. Не забудьте сбросить поставленную контрольную точку, кликнув по номеру строки еще раз.

Ошибка два: проблема определения языка.

Вы, возможно, обратили внимание на переменную lang;/*language*/ в начале скрипта. Можно предпложить, что код устанавливающий значение этой переменной и вызывает проблему. Можно попробовать найти этот код используя встроенную в отладчики функцию поиска. В Dragonfly поиск находтится прямо над просмотрщиком кода, в Firebug - в правом верхнем углу (см. рисунок 5)

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

  1. Напечатайте lang = в поле поиска.
  2. Установите контрольную точку на строке, где переменной lang задается значение.
  3. Перезагрузите страницу.
У WebInspector тоже есть очень удобная функция поиска. Она позволяет искать что угодно одновременно и в разметке страницы, и в CSS, и в коде JavaScript. Результаты показывюется на отдельной панели, где вы можете дважды кликнуть по ним, чтобы перейти в нужное место, как показано на скриншоте.


рис. 5: поиск в Dragonfly и в WebInspector.

Для того, чтобы проверить, что делает эта функция:

  1. Нажмите кнопку «step into» для входа внутрь функции getLanguage.
  2. Жмите ее еще и еще, пошагово выполняя код
  3. В окне просмотра переменных смотрите как меняются их значния.
Войдя в функцию вы увидите попытку прочитать язык из строки юзер-агента браузера, путем анализа navigator.userAgent.
var str1 = navigator.userAgent.match(/\((.*)\)/);
var ar1 = str1.split(/\s*;\s*/), lang;
for (var i = 0; i < ar1.length; i++){
if (ar1[i].match(/^(.{2})$/)){
lang = ar1[i];
}
}


В процессе пошагового прохождения кода, вы можете использовать окно просмотра локальных переменных. На рисунке 6 показано как это выглядит в Firebug и IE8 DT, массив ar1 мы развернули, чтобы видеть его элементы.

рис. 6: Панель просмотра локальных переменных фукции getLanguage в Firebug IE8’s

Выражение ar1[i].match(/^(.{2})$/) просто ищет строку, состоящую их двух символов, типа «no», «en». Однако как видно на скриншоте у Firefox информация о языке представлена в виде «nn-NO» (2) . IE же и вовсе не помещает в юзер-агента информации о языке.

Таким образом мы нашли вторую ошибку: определение языка производилось путем поиска двухбуквенного кода в строке юзерагента, но Firefox имеет пятисимвольное обозначение языка, а IE не имеет его вовсе. Такой код должен быть переписан и заменен на определение языка либо на стороне сервера с помощью HTTP заголовка Accept-Language, либо получением его из navigator.language (navigator.userLanguage для IE). Вот пример того, какой может быть такая функция

function getLanguage() {
var lang;

if (navigator.language) {
lang = navigator.language;
} else if (navigator.userLanguage) {
lang = navigator.userLanguage;
}

if (lang && lang.length > 2) {
lang = lang.substring(0, 2);
}

return lang;
}


Ошибка три: таинственная переменная «prop»


рис. 7: В панели просмотра переменных Firebug и Dragonfly видна глобальная переменная prop

На рисунке 7 хорошо видно переменную «prop». В хорошо написанных приложениях количество глобальных переменных должно быть минимально, поскольку они могут стать причиной проблем, когда, например две части приложения захотят использовать одну и ту же переменную. Предположим, что завтра другая команда добавит новые возможности в наше приложение и тоже объявит переменную «prop». Мы получим две разные части кода приложения, использующие одно имя для разных вещей. Такая ситуация часто приводит к конфликтам и ошибкам. Можно попробовать найти эту переменную и объявить ее локальной. Для этого можно воспользоваться поиском, как мы делали это в предыдущем случае, но есть и более умный способ…

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

__defineSetter__("prop" , function () { debugger; });

Сделайте следующее:
  1. Добавьте отладочный код в начало самого первого скрипта.
  2. Перезагрузите страницу.
  3. Отметьте, как прерывается выполнение скрипта.
В IE8 DT имеется закладка «Watch», однако прерывания в момент изменения переменной не происходит. Так что этот пример работает только в Firefox, Opera и Safari.

Когда вы перезагрузите страницу, выполнение кода немедленно остановится там где будет определена переменная «prop». Фактически остановка произодет в том месте, где вы добаили вышеупомянутую строку. Один клик по кнопке «step out» перекинет вас в место установки переменной.

for (prop in attributes) {
if (el.getAttribute(prop) != attributes) includeThisElement = false ;


Нетрудно заметить цикл for в котором объявляется переменная prop без ключевого слова var, т.е. глобальная. Исправить это несложно, просто допишем var и исправим ошибку.

Ошибка четыре: атрибут «clone», которого быть не должно

Четвертая ошибка очевидно была обнаружена продвинутым тестировщиком, использующим DOM инспектор, так как ее существование никак не проявляется в пользовательском интерфейсе приложения. Если и мы откроем DOM инспектор (в Firebug это закладка «HTML», в Dragonfly она называется «DOM»), то увидим что многие элементы имеют атрибут clone, которого быть не должно.

рис. 8: Dragonfly’s DOM инспектор показывает проблемный код.

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

Самый быстрый способ найти эту проблему состоит в том, чтобы установить контрольную точку, которая срабатывает тогда, когда атрибут с названием clone будет установлен для какого-нибудь HTML элемента. Могут ли отладчики сделать это?

JavaScript - очень гибкий язык, и одна из его сильных сторон (или слабых, в зависимости от вашей точки зрения) - это то, что вы можете заменить базовые функции языка своими собственными. Добавьте этот кусок кода на страницу, он переопределит системный метод setAttribute, вызывая остановку кода в момент установки свойства «clone»:

var funcSetAttr = Element.prototype.setAttribute; /* сохраняем ссылку на системный метод */
Element.prototype.setAttribute = function (name, value) {
if (name == "clone" ) {
debugger; /* останавливаем скрипт */
}
funcSetAttr.call(this ,name,value); /* вызываем ранее сохраненный системный метод, чтобы нормальные свойства устанавливались корректно */
};


Итак, делаем следующее:
  1. Добавьте приведенный код в начало первого скрипта на странице.
  2. Перезагрузите страницу.
После перезагрузки, скрипт начинает обрабатывать DOM-дерево, но сразу же останавливается, как только произойдет установка «плохого» атрибута. (Обратите внимание, что в текущих версиях Firefox, реализация setAttribute различна для разных элементов. Код, приведенный выше работает всегда как надо только в Опере; чтобы получить тот же самый эффект в Firefox, вы можете заменить слово Element на HTMLFormElement, чтобы переопределить более специфический метод HTMLFormElement.prototype.setAttribute).

Когда выполнение остановится в контрольной точке, вы захотите узнать где же произошел вызов setAttribute(), то есть вам нужно вернуться на уровень выше в цепочке вызовов функций и посмотреть что происходит там. Для этого вы можете использовать стек вызовов.


рис. 9: Стек вызовов в Dragonfly и IE8.

На рисунке 10 показан стек в Firebug. В строке "setAttribute " рядом с именем файла самой левой является текущая взванная функция.


рис. 10: Стек вызовов в Firebug. Самая последняя вызванная функция слева.

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

Как использовать стек вызовов, чтобы найти проблемную функцию:

  1. Нажмите на имя функции в стеке, которую вы хотите видеть.
  2. Обратите внимние, что локальные переменные обновляются на значения которые они имеют в выбраном контексте.
  3. Помните, что, если вы используете кнопки пошагового исполнения то они будут перемещать вас с места точки остановки, даже если вы находитесь в другой части стека.
Выбор makeElement перенесет нас в другую часть кода:
for (var prop in attributes) {
el.setAttribute(prop, attributes);
}


где вы увидите вызов setAttribute. Панель локальных переменных показывает, что значение переменной «prop» действительно «clone». Переменная prop определена в цикле for...in. Это говорит нам о том, что так называется одно из свойств объекта «attributes». Данный объект передается в функцию вторым параметром. Если вы подниметесь по стеку еще на один уровень выше, то увидите следующий код:
var form = makeElement(‘form’, { action:’/login’, method:’post’, name:’loginform’ } , document .body);

Второй параметр метода подсвечен жирным - у этого объекта нет свойства clone. Так откуда же оно взялось?

Давайте еще раз вернемся в функцию makeElement и внимательно посмотрим на переменную attribute и её свойство «clone». Вы можете кликнуть по значению-функции этого свойства для перехода к месту, где оно назначается, оно будет подсвечено голубым цветом

рис. 11: Firebug показывает нам, где было определено свойство clone.

Вот мы и нашли причину четвертой ошибки: метод clone добавляется всем объектам с помощью Object.prototype. Такой подход считается плохой практикой, потому что в циклах for...in объектов будут видны все свойства заданные вами через Object.prototype. Это может приводить к очень трудно уловимым ошибкам.

Чтобы исправить эту ошибку, можно переместить метод clone из прототипа объекта непосредственно в сам объект, после чего заменить все вызовы obj.clone() на Object.clone(obj), как показано в примере:

// ПЛОХО, так делать не стоит
Object.prototype.clone = function () {
var obj = {};
for (var prop in this ) {
obj = this ;
}
return obj;
}
// Код. демонстрирующий использование метода clone():
var myObj1 = { "id" : "1" };
var myObj2 = myObj1.clone();

Сделайте лучше так:
Опубликовано: 26 марта 2013

Chrome Developer Tools — на мой взгляд, самый удобный инструмент веб-разработки. Он содержит в себе весь необходимый функционал для создания и отладки полноценных веб-приложений. Но с ним, как и с любым другим инструментом, нужно научиться работать. Начнем с основ.

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

Консоль дает разработчику доступ к ряду удобных и полезных функций. Рассмотрим основные из них:

console.log() , console.error() , console.warn() и console.debug()

Базовые функции вывода в консоль, позволяют выводить в консоль произвольные сообщения. Отличаются классификацией выводимых сообщений: error() помечает сообщения как ошибки, warn() помечает сообщения как предупреждения, debug() помечает сообщения как отладочные.

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

Console.log("Время регистрации:", 1121102802);

Также есть поддержка форматирования:

Console.log("Время регистрации: %d", 1121102802);

Поддерживаемые указатели формата:

// %s — строка console.log("%s", "Привет"); // %d, %i — целое число console.log("%d", 1337 / 42); // %f — число с плавающей запятой console.log("%f", 1337 / 42); // %o — элемент DOM console.log("%o", document.body); // либо console.dirxml(document.body); // %O — элемент JavaScript console.log("%O", document.body); // либо console.dir(document.body); // %c — вывод с заданием CSS стилей console.log("%cпривет %cмир", "color: red", "color: blue");

console.trace()

Выводит стек вызовов из точки в коде, где был вызван метод. Стек вызовов включает имена файлов и номера строк плюс счетчик вызовов метода trace() из одной и той-же точки.

console.assert()

Функция assert проверяет выражение, переданное первым параметром, и если выражение ложно, записывает в консоль ошибку вместе со стеком вызовов:

Var two = 3; var three = 2; console.assert(two < three, "два меньше трех");

console.group() , console.groupCollapsed() и console.groupEnd()

Функции для группировки вывода. Функция group() открывает группу сообщений, в качестве параметра принимает название группы (поддерживается форматирование, как в console.log()), а функция groupEnd() закрывает последнюю открытую группу. Функция groupCollapsed() аналогична функции group() , но создаваемая группа сообщений свернута по умолчанию.

console.time() и console.timeEnd()

Функции для вычисления времени исполнения кода. Функция time() запускает таймер, а функция timeEnd() останавливает таймер и выводит его значение. Обе функции принимают название таймера в качестве обязательного параметра.

Фильтр сообщений

В правом нижнем углу на вкладке консоли расположен фильтр сообщений по типу. All соответствует всем сообщениям, Errors — ошибкам и выводу функции console.error() , Warnings — предупреждениям и выводу функции console.warn() , Logs — выводу функции console.log() , Debug — выводу функций console.debug() , console.timeEnd() и прочей информации.

Взаимодействие с другими вкладками

debugger;

Когда браузер достигает строчки debugger; в любом коде, он автоматически останавливает выполнение скрипта в этой точке и переходит на вкладку Скриптов (Sources).

$() , $$() и $x()

Функции, упрощающие выборку элементов, работают только в консоли. Функция $() возвращает первый элемент, соответствующий переданному селектору. Вторым параметром можно передать контекст поиска:

$("head") // возвращает элемент head $("head", document.body) // возвращает null, потому что body не содержит элементов head

Функция $$() аналогична $() , но возвращает все найденные элементы:

$$("script") // возвращает все элементы script $$("script", document.body) // возвращает все элементы script, содержащиеся в body

Функция $x() возвращает все элементы, соответствующие выражению XPath. Вторым параметром можно передать контекст:

$x("//script") // возвращает все элементы script $x("script", document.body); // возвращает все элементы script, содержащиеся непосредственно в body

Многие JavaScript фреймворки определяют свою функцию $() , в связи с чем значение функций в консоли также меняется.

$0 — $4

Консоль хранит в памяти ссылки на последние пять элементов, выделенных во вкладке Элементов (Elements). Для доступа к ним используются переменные $0 , $1 , $2 , $3 и $4 . $0 хранит ссылку на текущий выделенный элемент, $1 — на предыдущий и так далее.

$_

Переменная $_ хранит результат отработки последней команды в консоли. Это позволяет использовать результат выполнения одной команды в другой команде. Попробуйте выполнить эти команды по очереди:

1337 / 42; console.log("%d", $_);

inspect()

Функция inspect() открывает переданный объект или элемент на соответствующей ему вкладке:

Inspect($("head script")) // откроет вкладку Elements и выделит первый тег script найденный внутри head

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

Визуальная отладка

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

Консоль API – это объект (console), который можно использовать для вывода отладочной информации (его можно использовать, как только страница будет загружена браузером). Наибольшую эффективность консоль показывает при работе с JavaScript.

Отладка javascript firebug

Как отслеживать события

Firefox - Записывать события

Firefox + Firebug + Firequery = Показывает события навешанные при помощи jQuery

Тормозит - вне работы выключать

Забудьте об отладке при помощи console.log навсегда! Изучите, как использовать точки останова для отладки кода в инструментах разработчика Chrome

Перевод статьи Brandon Morelli : Learn How To Debug JavaScript with Chrome DevTools . Опубликовано с разрешения автора.

Поиск и исправление ошибок может быть затруднительным. Вы можете поддаться соблазну бесконтрольно использовать console.log() , чтобы заставить ваш код работать правильно. С этим покончено!

Эта статья о правильном пути отладки! Вы узнаете, как использовать инструменты разработчика Chrome для настройки точек останова и исследования кода. Такой подход часто наиболее эффективный способ поиска и исправления ошибок в коде.

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

Шаг 1: Воспроизводим ошибку

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

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

  • Вот веб-страница, с которой мы будем работать в рамках этой статьи. Открывайте её в новой вкладке: ДЕМО .
  • В демо для Number 1 введите 5 .
  • Введите 1 для Number 2 .
  • Нажмите Add Number 1 and Number 2 .
  • Посмотрите на метку ниже инпутов и кнопки. Она говорит, что 5 + 1 = 51 .

Упс. Это неверный результат. Результат должен быть равен 6 . Это и есть ошибка, которую мы собираемся исправить.

Шаг 2: Приостанавливаем выполнение кода с помощью точки останова

DevTools позволяет приостановить ваш код посреди его выполнения и получить значения всех переменных в этот момент времени. Инструмент для приостановки кода называется точкой останова. Попробуйте прямо сейчас:

  • Вернитесь к демо и откройте DevTools, нажав Command+Option+I (Mac) или Control+Shift+I (Windows, Linux).
  • Перейдите во вкладку Sources .
  • Нажмите Event Listener Breakpoints , чтобы развернуть меню. DevTools раскрывает список категорий событий, таких как Animation и Clipboard .
  • Разверните категорию событий Mouse .
  • Выберите click .
  • Вернувшись к демо, снова нажмите Add Number 1 and Number 2 . DevTools приостановит работу и выделит строку кода в панели Sources :
function onClick() {

Когда вы выбираете click, вы устанавливаете точку останова на основе всех событий click . Когда происходит клик по любой ноде и эта нода имеет обработчик события click , DevTools автоматически останавливает исполнение на первой строке кода обработчика click для этой ноды.

Шаг 3: Исследуем код

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

  • На панели Sources в DevTools нажмите Step into next function call .
кнопка Step into next function call

Эта кнопка позволяет вам осуществить выполнение функции onClick() по одной строке за раз. DevTools остановит выполнение и выделит следующую строку кода:

If (inputsAreEmpty()) {

  • Теперь нажмите кнопку Step over next function call .
кнопка Step over next function call

Это говорит DevTools выполнить функцию inputAreEmpty() , не заходя в неё. Обратите внимание, что DevTools пропускает несколько строк кода. Это происходит из-за того, что inputAreEmpty() расценивается как false , поэтому блок кода оператора if не выполняется.

Это основная идея исследования кода. Если вы посмотрите на код get-started.js , вы увидите, что ошибка, вероятно, находится где-то в функции updateLabel() . Вместо того, чтобы исследовать каждую строку кода, вы можете использовать другой тип точки останова, чтобы приостановить код ближе к месту ошибки.

Шаг 4: Устанавливаем другую точку останова

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

  • Посмотрите на последнюю строку кода в updateLabel() :
label.textContent = addend1 + "+" + addend2 + "=" + sum;

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

  • Нажмите кнопку Resume script execution :
кнопка Resume script execution

Сценарий будет выполняться до тех пор, пока не встретит точку останова.

  • Посмотрите на уже выполненные строки кода в updateLabel() . DevTools выводит значения addend1 , addend2 и sum .

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

Шаг 5: Проверяем значения переменных

Другая распространенная причина ошибок: переменная или функция генерируют значения, отличные от ожидаемых. Чтобы увидеть, как значения меняются со временем, многие разработчики используют console.log() , но console.log() может утомлять и быть неэффективным по двум причинам. Во-первых, вам может потребоваться вручную отредактировать код с большим количеством вызовов console.log() . Во-вторых, вы можете не знать точно, какая переменная связана с ошибкой, поэтому вам может потребоваться залогировать множество переменных.

Watch Expressions - альтернатива от DevTools для console.log() . Используйте Watch Expressions для отслеживания значения переменных во времени. Как следует из названия, Watch Expressions не ограничиваются только переменными. Вы можете сохранить любое допустимое выражение JavaScript в Watch Expression. Попробуйте прямо сейчас:

  • На панели Sources DevTools нажмите Watch . Секция раскроется.
  • Нажмите Add Expression .
кнопка Add Expression
  • Введите typeof sum .
  • Нажмите Enter. DevTools покажет: typeof sum: "string" . Значение справа от двоеточия является результатом вашего Watch Expression.

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