Введение в ошибки в JavaScript

Введение в ошибки в JavaScript

Технический фундамент ошибок в рантайме

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

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

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

Зачем вообще разбираться с ошибками

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

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

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

Какие ошибки бывают чаще всего

На старте полезно разделить ошибки на 3 группы:

  • синтаксические (SyntaxError) - код нельзя даже разобрать;
  • ошибки времени выполнения (TypeError, ReferenceError и другие) - код запустился, но упал в процессе;
  • логические ошибки - код работает без падения, но результат неверный.

Смотри, что важно: try...catch помогает только с ошибками, которые происходят во время выполнения (runtime). Синтаксическая ошибка в коде (когда файл не парсится) остановит запуск скрипта, и try...catch в этом же файле не спасет.

При этом тип SyntaxError может встретиться и как runtime-ошибка, например при парсинге JSON:

try {
  JSON.parse('{bad json}');
} catch (error) {
  console.log(error.name); // SyntaxError
}

Смотри, что важно: третья категория самая коварная. Приложение не падает, но бизнес-логика ломается, и баг замечают пользователи.

const price = 100;
const discount = 20;

// Логическая ошибка: ожидали 80, получили 2000
const total = price * discount;
console.log(total);

Код синтаксически валиден, рантайм не ругается, но формула неправильная. Это типичный пример, почему тесты и проверки нужны даже там, где "ничего не падает".

Проверь себя: чем логическая ошибка отличается от TypeError с точки зрения видимости проблемы?

Базовые встроенные типы ошибок

JavaScript уже содержит стандартные классы ошибок. Несколько базовых, которые ты будешь видеть постоянно:

  • ReferenceError - обращение к переменной, которой нет в области видимости;
  • TypeError - попытка сделать операцию с неподходящим типом;
  • SyntaxError - неправильный синтаксис;
  • RangeError - значение вышло за допустимый диапазон.
function printUser(user) {
  console.log(user.name.toUpperCase());
}

printUser(null); // TypeError: Cannot read properties of null

Здесь часто путаются: ошибка не в toUpperCase, а в том, что user равен null, и у него нет свойства name. То есть корневая причина обычно находится чуть раньше места падения.

Проверь себя: какая минимальная проверка перед user.name спасет код от падения?

Почему ошибки появляются в реальных сценариях

Ошибки чаще всего приходят из границ системы:

  • пользовательский ввод: пустые строки, пробелы, неожиданные символы;
  • внешние данные: API может вернуть null или неполный объект;
  • несогласованность кода: функция ожидает одно, а получает другое;
  • изменения в проекте: рефакторинг сломал старые места вызова.

Мини-сценарий: форма регистрации. Ты ждешь email-строку, а приходит undefined. Если сразу вызвать trim(), получишь TypeError.

function normalizeEmail(email) {
  if (typeof email !== 'string') return null;
  return email.trim().toLowerCase();
}

console.log(normalizeEmail('  USER@MAIL.COM ')); // user@mail.com
console.log(normalizeEmail(undefined)); // null

Дополнительный пример: защита от ReferenceError через явную область видимости.

function printTotal() {
  const total = 100;
  console.log(total);
}

printTotal();
// console.log(total); // ReferenceError: total is not defined

Анти-провал: сначала валидируй вход, потом вызывай методы. Не наоборот.

Стек вызовов и чтение сообщения об ошибке

Когда ошибка выбрасывается, JavaScript показывает:

  • тип ошибки (TypeError, ReferenceError);
  • сообщение (Cannot read properties of null);
  • stack trace - цепочку вызовов до места падения.

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

Мини-сценарий: обработка данных API.

  • renderProfile вызывает formatName;
  • formatName ожидает user.firstName;
  • API вернул объект без firstName;
  • падаешь в formatName, но причина в контракте данных.

Проверь себя: почему исправление только в renderProfile может не решить проблему системно?

Частые ошибки новичков

  • Игнорировать текст ошибки и смотреть только на красный экран.
  • Сразу переписывать много кода вместо локальной проверки входов.
  • Логировать слишком мало (не видно данных) или слишком много (шум).
  • Считать, что "если не упало, значит работает правильно".

Еще одна частая ловушка: пытаться лечить симптом, а не причину. Например, ставить "магические" проверки в одном месте, когда нужно исправить формат данных на границе модуля.

Небольшой рабочий флоу отладки на старте

  1. Зафиксируй точный сценарий: какие данные и шаги приводят к багу.
  2. Прочитай тип ошибки и сообщение полностью.
  3. Найди место падения по stack trace.
  4. Проверь входные данные в этой точке.
  5. Сформулируй гипотезу и проверь минимальным изменением.

Это простой процесс, но он сильно ускоряет работу и снижает "хаотичную" отладку.

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

Краткий итог

  • Ошибки в JavaScript это нормальная часть разработки, а не "провал".
  • Есть синтаксические, runtime и логические ошибки, и каждая требует своего подхода.
  • Самые частые падения у новичков связаны с неверными типами и отсутствующими значениями.
  • Корневая причина часто находится на границе данных, а не в строке, где упало.
  • Четкий флоу: воспроизвести -> прочитать сообщение -> проверить вход -> исправить причину.