5.01. Консоль, отладка и боль
Консоль, отладка и боль
Базовая отладка в консоли
Хотелось бы отметить, что JavaScript на практике не всегда такой «чёткий», как в теории. Вроде бы логично - блоки кода, наборы функций, циклов, операторов и переменных, которые работают с элементами и прочими объектами, позволяют взаимодействовать с другими компонентами сайта или приложения. Но сам код написать намного легче - сложнее его отладить.
Отладка — это неотъемлемая часть разработки на JavaScript. Благодаря инструментам разработчика (DevTools), доступным в современных браузерах (Chrome, Firefox, Edge и др.), можно легко находить ошибки, анализировать выполнение кода, проверять значения переменных и определять, почему тот или иной участок кода работает некорректно.
Как мы уже отмечали, в браузере это открывается через меню или по горячей клавише F12, либо Ctrl+Shift+I (Cmd+Option+I на macOS). Когда мы пишем «console.log()», мы вызываем объект консоли и его метод log(), в который передаём значение — это можно использовать в качестве простейшего способа проверки запускаемости метода - на практике можно в сомнительные функции добавить вывод значения, к примеру, переменной, в консоль. Если вывода не произошло - значит функция не вызвана, а если значение переменной - undefined, значит получили его некорректно. Но это лишь пример.
Выводить можно log(), ошибки, предупреждения - console.error(), console.warn() и т.д., а для красивого вывода массивов и объектов есть console.table().
И консоль — это не только вывод, но и ввод - можно выполнять произвольный JavaScript прямо в консоли, искать элементы DOM ($0, document.querySelector(), document.getElementById()), получать значения переменных.
Учебник https://learn.javascript.ru/ приводит замечательный пример работы консоли - для этого нужно открыть страницу по ссылке:
https://learn.javascript.ru/article/devtools/bug.html

Тут можно увидеть, что в HTML-коде подключен скрипт через <script>, и в содержимом тега указано «lalala», и если открыть консоль, то будет видна ошибка - lalala is not defined. Так и работает работа с ошибками в консоли - если в скрипте есть проблема, то отлаживается она именно так - и обратите внимание, несмотря на проблему, страница открывается.
Часто JS-код разделён на несколько файлов. Чтобы найти нужный, нужно во вкладке Sources (Источники) просмотреть структуру проекта слева, использовать поиск по файлам (Ctrl+P), а для поиска конкретного кода можно использовать Ctrl+F внутри файла или глобальный поиск по всем файлам. Это используется для нахождения нужного фрагмента кода - к примеру, там тысячи строк, и вам нужна конкретная функция - вы просто ищете её в поиске, переходите к ней и работаете.
Если нужно понять, какой код вызывается при нажатии на кнопку, можно навести на элемент в DOM (через «Элементы»/ «Elements») - там будут указаны обработчики событий.
Когда я сказал «работаете», я имел в виду обработку нужной нам функции. К примеру, мы хотим выяснить, всё ли работает как надо - тут нужна установка точки останова (Breakpoints). Точка останова позволяет приостановить выполнение скрипта на определённой строке кода. Это помогает проанализировать состояние программы «в реальном времени».

Во вкладке «Источники», когда мы нашли нужный JS-файл, нужную строку с функцией - нужно кликнуть по номеру строки слева - появится синяя точка. При выполнении кода браузер остановится на этой строке, и это позволит просмотреть текущие значения переменных, пошагово выполнять код (Step Over / Step Into), продолжать выполнение.
Помните, мы говорили о том, что JS интерпретируемый и работает построчно? Вот так это и можно увидеть - когда запускаете код, он выполняется строка за строкой, и через отладку можно отследить, словно поэтапно выслеживая - «…так, строка успешна, следующая тоже успешна, а тут проблема!» и при выявлении некорректного поведения можно идти править код.
Альтернативный способ (без поиска файла в консоли) — это debugger. Прямо в код можно добавить строку:
debugger;
Браузер остановится на этом месте, если DevTools открыт, и можно пошагово продолжать выполнение.
В консоли можно напрямую вызвать любую функцию, если она доступна в текущей области видимости, допустим указав «myFunction()». А чтобы проверить, существует ли функция, можно и написать проверки, к примеру:
typeof myFunction === 'function' ? console.log("Функция есть") : console.log("Функции нет");
Для поиска методов объекта:
console.dir(myObject); // покажет все свойства и методы
Используйте автодополнение в консоли: наберите имя объекта и точку — появится выпадающий список методов и свойств.
Какие ещё можно дать советы при отладке? Проверяйте порядок загрузки скриптов — может быть, функция не определена, потому что скрипт ещё не загружен. Следите за асинхронностью — если данные приходят из fetch/ajax, то переменная может быть undefined до окончания запроса. Не забывайте очищать кэш и делать перезагрузку — иногда старый JS мешает работе нового кода. В режиме разработчика можно нажать правой кнопкой мыши на кнопку обновления в браузере и выполнить жёсткую перезагрузку с очисткой кеша.
Отладка JavaScript в браузере
Инструменты разработчика в современных браузерах
Инструменты разработчика представляют собой встроенный набор утилит для анализа и отладки веб-приложений. Все основные браузеры предоставляют собственные инструменты с похожей функциональностью.
Структура инструментов разработчика
Инструменты разработчика включают несколько основных панелей:
- Консоль — отображение сообщений, ошибок, предупреждений и выполнение JavaScript команд
- Источники — просмотр и отладка исходного кода с возможностью установки точек останова
- Сеть — мониторинг сетевых запросов и ответов
- Элементы — инспектирование и редактирование DOM дерева
- Производительность — анализ производительности приложения
- Память — профилирование использования памяти
Каждая панель предоставляет специализированные инструменты для решения конкретных задач отладки.
Доступ к инструментам разработчика
Открыть инструменты разработчика можно несколькими способами:
- Клавиша F12 на клавиатуре
- Комбинация клавиш Ctrl+Shift+I (Windows/Linux) или Cmd+Option+I (Mac)
- Правый клик мыши на странице и выбор пункта "Просмотреть код" или "Inspect Element"
- Меню браузера → Дополнительные инструменты → Инструменты разработчика
Разные браузеры используют собственные названия для инструментов разработчика. Chrome и Edge называют их "Developer Tools", Firefox использует "Web Developer Tools", Safari предоставляет "Web Inspector".
Чтение сообщений об ошибках в консоли
Консоль браузера является первым местом, куда попадают все сообщения об ошибках выполнения кода. Понимание структуры этих сообщений помогает быстро локализовать проблему.
Типы сообщений в консоли
Консоль отображает несколько типов сообщений:
- Ошибки — критические проблемы, прерывающие выполнение кода
- Предупреждения — потенциальные проблемы, не останавливающие выполнение
- Информационные сообщения — дополнительная информация о работе приложения
- Логи — сообщения, добавленные разработчиками через
console.log()
Каждый тип сообщения имеет свой цвет и иконку для быстрой визуальной идентификации.
Структура сообщения об ошибке
Типичное сообщение об ошибке включает следующие компоненты:
Uncaught TypeError: Cannot read properties of undefined (reading 'name')
at getUserData (app.js:45:18)
at displayUserInfo (app.js:62:12)
at init (app.js:80:8)
Разбор структуры сообщения:
- Uncaught TypeError — тип ошибки и указание, что она не была перехвачена
- Cannot read properties of undefined — описание проблемы
- (reading 'name') — конкретное свойство, доступ к которому вызвал ошибку
- at getUserData (app.js:45:18) — имя функции, файл, строка и столбец
- Стек вызовов — цепочка функций, приведших к ошибке
Такая структура позволяет точно определить местоположение ошибки в коде.
Распространённые типы ошибок JavaScript
JavaScript генерирует несколько стандартных типов ошибок при выполнении кода.
ReferenceError
Ошибка возникает при попытке обратиться к несуществующей переменной или функции:
console.log(nonExistentVariable);
// Uncaught ReferenceError: nonExistentVariable is not defined
Также возникает при обращении к переменной до её инициализации:
console.log(myVar);
let myVar = 'value';
// Uncaught ReferenceError: Cannot access 'myVar' before initialization
TypeError
Ошибка появляется при попытке выполнить операцию с несовместимым типом данных:
const obj = null;
console.log(obj.property);
// Uncaught TypeError: Cannot read properties of null (reading 'property')
const num = 42;
num();
// Uncaught TypeError: num is not a function
SyntaxError
Ошибка возникает при нарушении синтаксиса JavaScript:
const obj = { name: 'John' age: 30 };
// Uncaught SyntaxError: Unexpected identifier
function test() {
return
{
value: 42
}
}
// Uncaught SyntaxError: Unexpected token '{'
RangeError
Ошибка появляется при работе с числовыми значениями вне допустимого диапазона:
const arr = new Array(-1);
// Uncaught RangeError: Invalid array length
function recurse() {
recurse();
}
recurse();
// Uncaught RangeError: Maximum call stack size exceeded
Анализ стека вызовов (StackTrace)
Стек вызовов представляет собой последовательность функций, которые были вызваны до момента возникновения ошибки. Анализ стека вызовов помогает понять путь, по которому ошибка попала в приложение.
Структура стека вызовов
Стек вызовов отображается в обратном порядке — от последней вызванной функции к первой:
function levelThree() {
const data = null;
return data.value; // Ошибка здесь
}
function levelTwo() {
return levelThree();
}
function levelOne() {
return levelTwo();
}
function start() {
return levelOne();
}
start();
Результат выполнения:
Uncaught TypeError: Cannot read properties of null (reading 'value')
at levelThree (script.js:3:12)
at levelTwo (script.js:7:12)
at levelOne (script.js:11:12)
at start (script.js:15:12)
at script.js:18:1
Стек показывает полный путь от функции start() до места возникновения ошибки в levelThree().
Практическое использование стека вызовов
При анализе стека вызовов важно обращать внимание на несколько аспектов:
- Первая строка стека указывает на точное место возникновения ошибки
- Последовательность вызовов показывает, как ошибка распространилась по приложению
- Имена функций помогают понять контекст выполнения
- Номера строк и столбцов позволяют быстро перейти к проблемному коду
В сложных приложениях стек вызовов может содержать десятки записей. В таких случаях полезно искать переходы между разными модулями или файлами.
Стек вызовов в асинхронном коде
Асинхронный код создаёт дополнительные сложности при анализе стека вызовов:
function fetchData() {
return fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => processData(data))
.catch(error => console.error('Fetch error:', error));
}
function processData(data) {
return data.items.map(item => item.name.toUpperCase());
}
fetchData();
Если сервер вернёт ответ без поля items, стек вызовов будет выглядеть так:
Uncaught TypeError: Cannot read properties of undefined (reading 'map')
at processData (script.js:10:22)
at script.js:4:14
Стек показывает функцию processData, но не показывает полный путь через промисы. Современные браузеры улучшают отображение асинхронных стеков, но полная картина может быть недоступна.
Точки останова (Breakpoints)
Точки останова позволяют приостановить выполнение кода в определённом месте для детального анализа состояния приложения.
Типы точек останова
Браузер поддерживает несколько типов точек останова:
- Строчные точки останова — приостанавливают выполнение на конкретной строке кода
- Условные точки останова — срабатывают только при выполнении определённого условия
- Точки останова на изменениях DOM — срабатывают при изменении элементов страницы
- Точки останова на событиях — срабатывают при возникновении определённых событий
- Точки останова на исключениях — срабатывают при возникновении ошибок
Каждый тип точки останова решает конкретную задачу отладки.
Установка строчных точек останова
Строчные точки останова устанавливаются непосредственно в панели "Источники" инструментов разработчика:
- Открыть панель "Источники" (Sources)
- Найти нужный файл в дереве файлов
- Кликнуть по номеру строки, где нужно установить точку останова
- Появится красная точка, указывающая на активную точку останова
При выполнении кода доходит до строки с точкой останова, выполнение приостанавливается, и становится доступна информация о текущем состоянии.
Условные точки останова
Условные точки останова срабатывают только при выполнении заданного условия:
function processItems(items) {
for (let i = 0; i < items.length; i++) {
const item = items[i];
// Точка останова сработает только когда i === 5
console.log(item);
}
}
Установка условной точки останова:
- Правый клик по номеру строки
- Выбор "Добавить условную точку останова"
- Ввод условия, например:
i === 5 - Нажатие Enter
Точка останова сработает только при выполнении условия, что полезно при отладке циклов или обработки массивов.
Точки останова на исключениях
Точки останова на исключениях позволяют остановить выполнение кода при возникновении любой ошибки:
- Открыть панель "Источники"
- Найти панель "Точки останова" (Breakpoints)
- Активировать опцию "Приостанавливать на исключениях" (Pause on exceptions)
- Опционально активировать "Приостанавливать на перехваченных исключениях"
При активации этой опции браузер остановит выполнение кода в момент возникновения ошибки, даже если она будет перехвачена блоком try-catch.
Работа с консолью браузера
Консоль браузера предоставляет мощные инструменты для анализа и отладки кода в реальном времени.
Методы console для отладки
Объект console предоставляет множество методов для вывода информации:
// Базовый вывод
console.log('Обычное сообщение');
console.info('Информационное сообщение');
console.warn('Предупреждение');
console.error('Ошибка');
// Вывод с форматированием
console.log('Значение переменной: %s', variable);
console.log('Число: %d, Строка: %s', 42, 'test');
// Вывод объектов и таблиц
console.table([{name: 'John', age: 30}, {name: 'Jane', age: 25}]);
console.dir(document.body);
// Группировка сообщений
console.group('Группа сообщений');
console.log('Сообщение 1');
console.log('Сообщение 2');
console.groupEnd();
// Измерение времени выполнения
console.time('operation');
// Код для измерения
console.timeEnd('operation');
// Подсчёт вызовов
console.count('counter');
console.count('counter');
console.countReset('counter');
Каждый метод решает конкретную задачу отладки и предоставляет разную визуализацию данных.
Интерактивное выполнение кода
Консоль позволяет выполнять произвольный JavaScript код в контексте текущей страницы:
// Проверка значений переменных
document.querySelector('.header').style.color = 'red';
// Вызов функций
app.getUserData(123);
// Модификация состояния приложения
window.appState.user.loggedIn = false;
// Тестирование новых функций
function testHelper(value) {
return value * 2;
}
testHelper(21); // 42
Интерактивное выполнение кода помогает быстро проверить гипотезы и протестировать изменения без перезагрузки страницы.
Фильтрация сообщений в консоли
Консоль предоставляет инструменты для фильтрации сообщений:
- Фильтр по уровню: ошибки, предупреждения, информация, логи
- Фильтр по тексту: поиск по содержимому сообщений
- Фильтр по источнику: выбор сообщений из конкретных файлов
- Скрытие сообщений от браузера и расширений
Фильтрация помогает сосредоточиться на релевантных сообщениях при отладке сложных приложений.
Отладка минифицированного и обфусцированного кода
Минифицированный и обфусцированный код создаёт дополнительные сложности при отладке, так как исходный код сильно отличается от развёрнутой версии.
Особенности минифицированного кода
Минификация кода включает несколько преобразований:
- Удаление пробелов и переносов строк
- Сокращение имён переменных до одной буквы
- Удаление комментариев
- Оптимизация структуры кода
Пример минифицированного кода:
function a(b){return b.map(function(c){return c.name.toUpperCase()})}
Тот же код в развёрнутом виде:
function processUsers(users) {
return users.map(function(user) {
return user.name.toUpperCase();
});
}
Минифицированный код занимает меньше места, но значительно сложнее для чтения и отладки.
Использование source maps
Source maps представляют собой файлы сопоставления между минифицированным и исходным кодом. Они позволяют отлаживать минифицированный код как обычный развёрнутый код.
Подключение source map к минифицированному файлу:
// app.min.js
(function(){/* минифицированный код */})();
//# sourceMappingURL=app.min.js.map
Файл app.min.js.map содержит информацию о соответствии строк и переменных между минифицированной и исходной версиями.
Браузеры автоматически загружают и применяют source maps при наличии соответствующей ссылки в минифицированном файле.
Настройка отладки с source maps
Для эффективной отладки с использованием source maps необходимо:
- Убедиться, что файлы source maps доступны по указанному пути
- Проверить настройки инструментов разработчика для включения поддержки source maps
- В Chrome: Настройки → Источники → Включить source maps
- В Firefox: Настройки → Отладка → Включить source maps
При правильной настройке браузер будет показывать исходный код вместо минифицированного в панели "Источники".
Отладка без source maps
При отсутствии source maps отладка минифицированного кода требует дополнительных усилий:
- Использование поиска по тексту для локализации проблемных участков
- Анализ стека вызовов с учётом минифицированных имён функций
- Пошаговое выполнение кода для понимания логики
- Использование консоли для проверки значений переменных
В сложных случаях может потребоваться деминификация кода с помощью специальных инструментов.
Продвинутые техники отладки
Современные инструменты разработчика предоставляют дополнительные возможности для глубокого анализа приложений.
Мониторинг сетевых запросов
Панель "Сеть" (Network) позволяет отслеживать все сетевые запросы, выполняемые приложением:
- Заголовки запросов и ответов — информация о передаваемых данных
- Тело запросов и ответов — содержимое передаваемых данных
- Время выполнения — длительность каждого запроса
- Статус ответа — HTTP код ответа сервера
- Инициатор запроса — информация о том, какой код инициировал запрос
Мониторинг сетевых запросов помогает выявлять проблемы с API, медленные запросы и ошибки сервера.
Профилирование производительности
Профилирование производительности позволяет выявить узкие места в коде:
- Запись производительности — фиксация всех операций в течение определённого времени
- Анализ кадров — оценка производительности рендеринга
- Выявление долгих операций — поиск функций, занимающих много времени
- Анализ использования памяти — отслеживание утечек памяти
Профилирование помогает оптимизировать код и улучшить пользовательский опыт.
Отладка асинхронного кода
Асинхронный код требует специальных подходов к отладке:
- Точки останова в промисах — отслеживание состояния промисов
- Анализ очереди событий — понимание порядка выполнения асинхронных операций
- Отладка async/await — пошаговое выполнение асинхронных функций
- Мониторинг таймеров — отслеживание
setTimeoutиsetInterval
Современные браузеры предоставляют специальные инструменты для отладки асинхронного кода, включая визуализацию цепочек промисов.
Отладка событий
Отладка событий позволяет отслеживать обработчики событий и их выполнение:
- Точки останова на событиях — приостановка выполнения при возникновении события
- Мониторинг обработчиков — просмотр всех зарегистрированных обработчиков
- Анализ всплытия событий — отслеживание пути события по DOM дереву
- Отладка пользовательских событий — анализ событий, созданных разработчиками
Отладка событий помогает понять поведение интерактивных элементов и выявить проблемы с обработкой пользовательского ввода.
Инструменты для работы с ошибками
Эффективная работа с ошибками требует использования специализированных инструментов и подходов.
Глобальный обработчик ошибок
Глобальный обработчик ошибок позволяет перехватывать все необработанные ошибки в приложении:
window.addEventListener('error', function(event) {
console.error('Глобальная ошибка:', event.message);
console.error('Файл:', event.filename);
console.error('Строка:', event.lineno);
console.error('Столбец:', event.colno);
console.error('Ошибка:', event.error);
// Предотвращение стандартного обработчика
event.preventDefault();
});
window.addEventListener('unhandledrejection', function(event) {
console.error('Необработанное промис-исключение:', event.reason);
event.preventDefault();
});
Глобальный обработчик помогает собирать информацию об ошибках и предотвращать падение приложения.
Пользовательские точки останова
Пользовательские точки останова позволяют приостанавливать выполнение кода в определённых условиях:
function validateUser(user) {
if (!user.email) {
debugger; // Точка останова сработает при отсутствии email
}
if (user.age < 18) {
debugger; // Точка останова сработает для несовершеннолетних
}
return true;
}
Ключевое слово debugger вставляется непосредственно в код и срабатывает только при открытых инструментах разработчика.
Мониторинг производительности
Мониторинг производительности помогает выявлять проблемы до их проявления в виде ошибок:
// Измерение времени выполнения функции
console.time('fetchData');
fetchData().then(() => {
console.timeEnd('fetchData');
});
// Мониторинг частоты вызовов
let callCount = 0;
function monitoredFunction() {
callCount++;
if (callCount > 1000) {
console.warn('Функция вызвана слишком часто:', callCount);
}
// Основная логика
}
Проактивный мониторинг помогает предотвращать проблемы и улучшать качество кода.
Анализ сложных ошибок
Сложные ошибки требуют систематического подхода к анализу и устранению.
Цепочка вызовов и распространение ошибок
Ошибки в одной функции могут распространяться по цепочке вызовов:
function getUserName(userId) {
const user = database.findUser(userId);
return user.name; // Ошибка, если user === null
}
function displayUserInfo(userId) {
const name = getUserName(userId);
document.getElementById('username').textContent = name;
}
function initPage() {
const userId = getCurrentUserId();
displayUserInfo(userId);
}
initPage();
Если database.findUser() вернёт null, ошибка возникнет в getUserName(), но проявится только при вызове initPage(). Анализ стека вызовов помогает проследить путь ошибки от источника до места проявления.
Ошибки в сторонних библиотеках
Ошибки в сторонних библиотеках требуют особого подхода:
- Анализ стека вызовов — поиск перехода от кода приложения к коду библиотеки
- Проверка версий — убедиться, что используется совместимая версия библиотеки
- Изучение документации — проверка правильности использования API
- Тестирование изолированно — воспроизведение ошибки вне контекста приложения
Понимание границ ответственности помогает быстро локализовать проблему.
Ошибки в асинхронном коде
Асинхронный код создаёт дополнительные сложности при отладке:
async function loadData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
return processData(data);
} catch (error) {
console.error('Ошибка загрузки данных:', error);
throw error;
}
}
function processData(data) {
return data.items.map(item => item.value);
}
Если сервер вернёт ответ без поля items, ошибка возникнет в processData(), но будет перехвачена в блоке catch функции loadData(). Правильная обработка ошибок в асинхронном коде требует внимательного анализа всей цепочки вызовов.
Ошибки в событиях и колбэках
Ошибки в обработчиках событий и колбэках могут быть сложноуловимыми:
button.addEventListener('click', function() {
try {
const result = calculateValue(input.value);
displayResult(result);
} catch (error) {
console.error('Ошибка обработки клика:', error);
}
});
function calculateValue(value) {
return value * 2; // Ошибка, если value не число
}
Ошибки в колбэках требуют локальной обработки или глобального перехвата через window.onerror.
Работа с современными фреймворками
Современные фреймворки предоставляют собственные инструменты для отладки и анализа.
Отладка React приложений
React Developer Tools предоставляют специализированные инструменты для отладки React приложений:
- Инспектирование компонентов — просмотр дерева компонентов и их состояния
- Мониторинг пропсов — отслеживание изменений пропсов компонентов
- Анализ хуков — просмотр состояния и эффектов хуков
- Профилирование производительности — анализ производительности компонентов
Установка React Developer Tools через расширение браузера добавляет новую панель в инструменты разработчика.
Отладка Vue приложений
Vue DevTools предоставляют аналогичные возможности для отладки Vue приложений:
- Инспектирование компонентов — просмотр иерархии компонентов
- Мониторинг состояния — отслеживание изменений в Vuex store
- Анализ событий — просмотр событий, генерируемых компонентами
- Отладка маршрутов — анализ навигации в Vue Router
Vue DevTools интегрируются с инструментами разработчика и предоставляют удобный интерфейс для анализа приложения.
Отладка Angular приложений
Angular предоставляет собственные инструменты для отладки:
- Augury — расширение для отладки Angular приложений
- Встроенные инструменты — использование
ng.probe()для инспектирования компонентов - Мониторинг изменений — отслеживание циклов изменения в приложении
- Анализ зависимостей — просмотр дерева внедрения зависимостей
Инструменты Angular помогают понять внутреннюю структуру приложения и выявить проблемы.
Локализация ошибок в больших приложениях
Анализ сообщений об ошибках
Сообщения об ошибках в консоли браузера содержат ключевую информацию для определения источника проблемы. Понимание структуры этих сообщений позволяет быстро находить причину сбоя.
Структура типичного сообщения об ошибке
Сообщение об ошибке включает несколько компонентов:
Uncaught TypeError: Cannot read properties of undefined (reading 'name')
at processUserData (app.js:145:23)
at handleResponse (app.js:210:18)
at fetch.then (app.js:267:12)
Разбор компонентов:
- Uncaught TypeError — тип ошибки и указание на отсутствие обработчика
- Cannot read properties of undefined — суть проблемы
- (reading 'name') — конкретное свойство, доступ к которому вызвал ошибку
- at processUserData (app.js:145:23) — имя функции, файл, строка и столбец
- Стек вызовов — последовательность функций, приведших к ошибке
Первая строка стека указывает на точное место возникновения ошибки, последующие строки показывают путь распространения ошибки.
Работа с минифицированным кодом
Минифицированный код представляет дополнительные сложности при анализе ошибок. Файлы с именами вроде script57.js и непонятными именами переменных затрудняют отладку.
Инструменты разработчика предоставляют функцию форматирования кода. Кнопка "Pretty print" преобразует минифицированный код в читаемый формат с отступами и переносами строк. Это не восстанавливает оригинальные имена переменных, но позволяет понять структуру кода.
Source maps решают проблему минифицированного кода полностью. Эти файлы содержат информацию о соответствии между минифицированными и исходными версиями кода. Браузер автоматически применяет source maps при их наличии, показывая в консоли и стеке вызовов оригинальные имена функций и номера строк исходного кода.
Пошаговая отладка кода
Пошаговая отладка позволяет выполнять код построчно, отслеживая изменения состояния приложения на каждом шаге.
Управление выполнением кода
При срабатывании точки останова становятся доступны кнопки управления выполнением:
- Возобновить выполнение — продолжить выполнение кода до следующей точки останова
- Шаг с заходом — выполнить текущую строку, войти в вызываемую функцию
- Шаг с обходом — выполнить текущую строку, не входя в вызываемые функции
- Шаг с выходом — выполнить код до выхода из текущей функции
Эти кнопки позволяют детально исследовать путь выполнения кода и находить место, где возникает ошибка.
Панель наблюдения
Панель наблюдения отображает текущие значения переменных и выражений в контексте выполнения. Она обновляется автоматически при каждом шаге отладки.
Добавление выражений в панель наблюдения позволяет отслеживать значения, которые не отображаются в стандартном списке переменных. Это полезно для сложных выражений или значений из внешних областей видимости.
Области видимости
Панель областей видимости показывает все переменные, доступные в текущем контексте выполнения:
- Локальная область — переменные, объявленные в текущей функции
- Замыкание — переменные из внешних функций, на которые ссылается текущий код
- Глобальная область — глобальные переменные и объекты
Понимание областей видимости помогает отслеживать, откуда берутся значения переменных и почему они могут иметь неожиданные значения.
Отладка асинхронного кода
Асинхронный код создаёт дополнительные сложности при отладке из-за нелинейного порядка выполнения.
Отладка промисов
Промисы выполняются асинхронно, что затрудняет отслеживание их состояния. Панель "Источники" предоставляет специальный раздел для мониторинга промисов.
Точки останова на промисах позволяют останавливать выполнение при переходе промиса в состояние выполнено или отклонено. Это помогает отслеживать обработку результатов асинхронных операций.
Отладка async/await
Функции async/await упрощают написание асинхронного кода, но не устраняют сложности отладки. Точки останова внутри асинхронных функций работают так же, как в синхронном коде.
Ключевое отличие — выполнение приостанавливается на операторах await, ожидая завершения промиса. Это позволяет исследовать состояние приложения до и после асинхронной операции.
Мониторинг очереди событий
Очередь событий управляет порядком выполнения асинхронного кода. Понимание её работы помогает предсказывать поведение приложения.
Инструменты разработчика не предоставляют прямого доступа к очереди событий, но анализ стека вызовов и порядка выполнения функций позволяет понять её состояние.
Работа с внешними зависимостями
Внешние библиотеки и фреймворки добавляют слои абстракции, затрудняющие отладку.
Изоляция проблем в стороннем коде
При возникновении ошибки в сторонней библиотеке важно определить, является ли проблема ошибкой в библиотеке или неправильным её использованием.
Анализ стека вызовов помогает найти переход от кода приложения к коду библиотеки. Если ошибка возникает сразу после вызова функции библиотеки с некорректными аргументами, проблема в коде приложения. Если ошибка возникает глубоко внутри библиотеки при корректных входных данных, проблема может быть в самой библиотеке.
Отладка минифицированных библиотек
Многие библиотеки распространяются в минифицированном виде. Для отладки таких библиотек необходимо использовать доступные source maps или деминифицированные версии.
Некоторые библиотеки предоставляют отладочные версии с понятными именами переменных и комментариями. Использование таких версий во время разработки упрощает отладку.
Мониторинг версий зависимостей
Несовместимость версий библиотек может вызывать неочевидные ошибки. Проверка используемых версий и их совместимости помогает предотвратить такие проблемы.
Инструменты сборки, такие как Webpack или Vite, предоставляют информацию о версиях зависимостей в процессе сборки. Анализ этой информации помогает выявить потенциальные конфликты.
Продвинутые техники отладки
Современные инструменты разработчика предоставляют дополнительные возможности для глубокого анализа приложений.
Условные точки останова
Условные точки останова срабатывают только при выполнении заданного условия. Это полезно при отладке циклов или функций, вызываемых многократно.
Установка условия для точки останова позволяет останавливать выполнение только в интересующих случаях, например, при определённом значении переменной или номере итерации цикла.
Точки останова на изменениях DOM
Изменения в DOM дереве могут вызывать неожиданное поведение приложения. Точки останова на изменениях DOM позволяют останавливать выполнение при модификации элементов страницы.
Три типа точек останова на изменениях DOM:
- Удаление узла — срабатывает при удалении элемента
- Изменение атрибутов — срабатывает при изменении атрибутов элемента
- Изменение поддерева — срабатывает при изменении дочерних элементов
Эти точки останова помогают отслеживать, какой код изменяет структуру страницы.
Точки останова на событиях
События пользовательского интерфейса, такие как клики или ввод текста, могут вызывать ошибки. Точки останова на событиях позволяют останавливать выполнение при возникновении определённых событий.
Панель "Источники" предоставляет список событий, на которые можно установить точки останова. При возникновении события выполнение приостанавливается, и становится доступен стек вызовов обработчика события.
Мониторинг производительности
Проблемы производительности могут проявляться как ошибки или неожиданное поведение. Панель "Производительность" позволяет записывать и анализировать выполнение кода.
Запись производительности фиксирует все операции, выполняемые приложением, включая выполнение JavaScript, рендеринг и перекомпоновку. Анализ записи помогает выявить долгие операции и узкие места в коде.
Работа с ошибками в продакшене
Ошибки в рабочем окружении требуют особого подхода к отладке.
Сбор информации об ошибках
Глобальные обработчики ошибок позволяют перехватывать и записывать все необработанные ошибки в приложении:
window.addEventListener('error', function(event) {
const errorInfo = {
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
stack: event.error?.stack,
timestamp: new Date().toISOString(),
userAgent: navigator.userAgent,
url: window.location.href
};
sendErrorToServer(errorInfo);
return false;
});
window.addEventListener('unhandledrejection', function(event) {
const errorInfo = {
reason: event.reason,
stack: event.reason?.stack,
timestamp: new Date().toISOString(),
url: window.location.href
};
sendErrorToServer(errorInfo);
event.preventDefault();
});
Сбор информации об ошибках помогает воспроизводить проблемы, возникающие у пользователей.
Воспроизведение ошибок
Воспроизведение ошибки — ключевой шаг в её устранении. Необходимо определить последовательность действий, приводящих к ошибке.
Инструменты записи сессий позволяют записывать действия пользователя и воспроизводить их для отладки. Это особенно полезно для ошибок, которые сложно воспроизвести вручную.
Анализ ошибок без доступа к коду
При отсутствии доступа к исходному коду отладка становится значительно сложнее. В таких случаях необходимо использовать доступные инструменты:
- Анализ стека вызовов — определение пути выполнения кода
- Мониторинг сетевых запросов — отслеживание взаимодействия с сервером
- Интерактивное выполнение кода — проверка гипотез через консоль
- Пошаговое выполнение — исследование логики минифицированного кода
Эти техники позволяют понять поведение приложения даже без доступа к исходному коду.
Интеграция с системами сборки
Современные системы сборки предоставляют инструменты для упрощения отладки.
Настройка source maps
Source maps должны быть правильно настроены в системе сборки для эффективной отладки. Разные системы сборки используют разные подходы к генерации source maps.
Webpack предоставляет несколько режимов генерации source maps:
- eval — быстрая генерация, но ограниченная функциональность
- source-map — полные source maps, но медленная генерация
- cheap-module-source-map — компромисс между скоростью и функциональностью
- inline-source-map — source maps встроены в файл, удобно для разработки
Выбор режима зависит от требований к скорости сборки и качеству отладки.
Отладка в режиме разработки
Режим разработки систем сборки предоставляет дополнительные инструменты для отладки:
- Горячая замена модулей — обновление кода без перезагрузки страницы
- Подробные сообщения об ошибках — расширенная информация о проблемах сборки
- Интеграция с инструментами разработчика — прямая связь между кодом и браузером
Использование режима разработки упрощает процесс отладки и ускоряет разработку.
Практические примеры отладки
Рассмотрим несколько типичных сценариев отладки и подходы к их решению.
Пример 1: Ошибка "Cannot read property of undefined"
Ошибка возникает при попытке доступа к свойству неопределённого значения:
function getUserEmail(user) {
return user.profile.email;
}
const userData = getUserData();
const email = getUserEmail(userData);
Если userData не содержит свойства profile, возникнет ошибка. Отладка:
- Установить точку останова на строке с обращением к
user.profile.email - Проверить значение переменной
userв панели наблюдения - Определить, почему
user.profileотсутствует - Проверить источник данных
userData - Добавить проверку перед доступом к свойству
Пример 2: Ошибка в асинхронном коде
Ошибка возникает при обработке ответа от сервера:
fetch('/api/users')
.then(response => response.json())
.then(data => {
const names = data.users.map(user => user.name);
displayNames(names);
});
Если сервер возвращает ответ без поля users, возникнет ошибка. Отладка:
- Установить точку останова внутри обработчика промиса
- Проверить структуру объекта
data - Определить, какое поле содержит массив пользователей
- Исправить обращение к данным
- Добавить обработку ошибок
Пример 3: Ошибка в сторонней библиотеке
Ошибка возникает при использовании сторонней библиотеки:
import { processData } from 'data-library';
const result = processData(inputData);
Отладка:
- Анализ стека вызовов для определения перехода к коду библиотеки
- Проверка документации библиотеки на предмет правильного использования
- Проверка версии библиотеки и её совместимости
- Тестирование библиотеки в изолированном окружении
- Поиск известных проблем в репозитории библиотеки
А в остальном - нужно сидеть, и разбираться...