Типы ошибок: Error, TypeError, ReferenceError
JavaScript имеет иерархию встроенных типов ошибок, каждый из которых сигнализирует об определённой причине сбоя; понимание различий помогает быстро диагностировать проблему и корректно её обрабатывать.
Зачем нужно
Правильная идентификация типа ошибки в catch-блоке позволяет реагировать по-разному: показать пользователю сообщение при TypeError, перезагрузить данные при NetworkError, логировать критически при неизвестном Error. Знание причин каждого типа помогает быстро найти баг.
Где используется
- Отладка и диагностика ошибок
- Дифференцированная обработка в
catch - Написание пользовательских ошибок, наследующих нужный тип
- Тестирование (jest:
expect(fn).toThrow(TypeError))
Иерархия встроенных ошибок
Error (базовый)
├── EvalError — ошибки eval (редко)
├── RangeError — значение вне допустимого диапазона
├── ReferenceError — обращение к несуществующей переменной
├── SyntaxError — синтаксическая ошибка в коде
├── TypeError — неверный тип значения или операция
├── URIError — неверный формат URI в encodeURI/decodeURI
└── AggregateError — несколько ошибок (Promise.any)
Error — базовый тип
const err = new Error('Что-то пошло не так');
console.log(err.name); // 'Error'
console.log(err.message); // 'Что-то пошло не так'
console.log(err.stack); // стек вызовов
// throw работает с любым значением, но throw Error — стандарт
throw new Error('Сообщение');
throw 'строка'; // плохая практика — нет стека
throw 42; // тоже плохая практика
TypeError — неверный тип
Самая частая ошибка в JavaScript:
// Обращение к свойству null/undefined
null.property; // TypeError: Cannot read properties of null
undefined.method; // TypeError: Cannot read properties of undefined
(null).toString(); // TypeError
// Вызов нефункции
const obj = { x: 1 };
obj.x; // TypeError: obj.x is not a function
// Неверный аргумент встроенного метода
Array.from(42); // TypeError: 42 is not iterable
// Мутация frozen объекта
const frozen = Object.freeze({ x: 1 });
frozen.x = 2; // TypeError (в strict mode): Cannot assign to read only property
ReferenceError — неизвестная переменная
// Обращение к необъявленной переменной
console.log(undeclared); // ReferenceError: undeclared is not defined
// Переменная до объявления (temporal dead zone — let/const)
console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 5;
// var — нет ReferenceError, но есть hoisting
console.log(y); // undefined (не ошибка!)
var y = 10;
RangeError — выход за допустимые границы
// Рекурсия без условия выхода
function infinite() { infinite; }
infinite; // RangeError: Maximum call stack size exceeded
// Невалидный размер массива
new Array(-1); // RangeError: Invalid array length
new Array(2**32); // RangeError: Invalid array length
// Неверный аргумент
(1.234).toFixed(200); // RangeError: toFixed digits must be between 0 and 100
SyntaxError — синтаксис
// Обычно возникает при парсинге кода, до выполнения
// eval("let x = ;"); // SyntaxError: Unexpected token ';'
// JSON.parse("{bad json}"); // SyntaxError: Unexpected token
try {
JSON.parse('{ не JSON }');
} catch (e) {
console.log(e instanceof SyntaxError); // true
}
Обработка разных типов
async function safeOperation() {
try {
await riskyOperation;
} catch (err) {
if (err instanceof TypeError) {
// Ошибка типа — скорее всего баг в коде
console.error('Ошибка типа:', err.message);
reportToBugTracker(err);
} else if (err instanceof RangeError) {
// Выход за диапазон — возможно некорректные данные
console.error('Неверное значение:', err.message);
showUserError('Некорректные данные');
} else if (err instanceof SyntaxError) {
// Синтаксическая ошибка — битые данные (напр. невалидный JSON)
console.error('Неверный формат:', err.message);
showUserError('Сервер вернул некорректный ответ');
} else {
// Неизвестная ошибка — пробрасываем
throw err;
}
}
}
Свойства объекта Error
const err = new TypeError('Неверный тип');
err.name; // 'TypeError'
err.message; // 'Неверный тип'
err.stack; // строка со стеком вызовов (нестандартно, но поддерживается везде)
err.cause; // ES2022: причина (другая ошибка)
// Error с cause
const original = new Error('Сеть недоступна');
const wrapped = new TypeError('Не удалось загрузить пользователя', { cause: original });
console.log(wrapped.cause); // Error: Сеть недоступна
Частые ошибки
1. Поглощение ошибок в catch
try {
doSomething;
} catch (e) {
// Плохо: все ошибки игнорируются
console.log('ошибка'); // маскируем баг!
}
// Хорошо: обрабатываем только известные, остальные пробрасываем
} catch (e) {
if (e instanceof KnownError) handleIt;
else throw e; // не глотаем неизвестные ошибки
}
2. throw строки вместо Error
throw 'Ошибка!'; // нет стека, нет instanceof, нет name
throw new Error('Ошибка!'); // правильно
Связанные темы
- Пользовательские ошибки
- Обработка ошибок в async коде
- Отладка -- console, debugger, breakpoints
- _MOC JavaScript