Типи помилок у JavaScript
У JavaScript усі помилки успадковуються від базового класу Error, а вбудованих спеціалізованих типів сім: ReferenceError, TypeError, RangeError, SyntaxError, URIError, EvalError і AggregateError. Кожен із них сигналізує про свій клас проблем, і на додачу ви завжди можете створити власний тип помилки, успадкувавшись від Error.
Теорія
TL;DR
Errorце базовий клас із властивостямиname,messageіstack.ReferenceError,TypeErrorіRangeErrorце три найчастіші помилки часу виконання.SyntaxErrorвиникає на етапі парсингу, тому звичайнимtry...catchйого не спіймати.URIErrorстосується функцій кодування URI,EvalErrorпрактично не використовується.AggregateErrorзбирає кілька помилок одразу, наприклад уPromise.any().- Власний тип помилки створюють через
class MyError extends Error.
Швидкий приклад
try {
null.toString();
} catch (e) {
console.log(e.name); // TypeError
console.log(e.message); // Cannot read properties of null
}Error, базовий клас помилок
Це універсальний тип, від якого успадковуються всі інші помилки. Якщо ви не знаєте, який тип помилки підходить, можна використати просто Error.
throw new Error("Something went wrong");Властивості об'єкта помилки:
name, ім'я помилки ("Error")message, описstack, трасування стека, показує, де саме сталася помилка
Помилки часу виконання: ReferenceError, TypeError, RangeError
ReferenceError, помилка посилання. Виникає, коли відбувається звертання до неіснуючої змінної або до властивості, недоступної в поточній області видимості.
console.log(x); // ReferenceError: x is not definedТакож може виникати при неправильному використанні this.
TypeError, помилка типу. Стається, коли операцію застосовують до значення невідповідного типу або намагаються викликати те, що не є функцією.
let n = null;
console.log(n.toString()); // TypeError: Cannot read properties of nulllet func = 123;
func(); // TypeError: func is not a functionRangeError, вихід за допустимі межі. Виникає, коли передане значення поза допустимим діапазоном.
new Array(-5); // RangeError: Invalid array length(123.456).toFixed(200);
// RangeError: toFixed() digits argument must be between 0 and 100SyntaxError, URIError, EvalError і AggregateError
SyntaxError, синтаксична помилка. Помилка при порушенні синтаксису JavaScript. Рушій не може розібрати код, тому програма навіть не запускається.
eval("if (true { console.log('hi'); }");
// SyntaxError: Unexpected token '{'Такі помилки не можна спіймати через
try...catch, бо вони стаються до початку виконання. Виняток, це код, який парситься окремо і пізніше, як у прикладі зevalвище або уnew Function(...).
URIError, помилка в URI-функціях. Стається, якщо функції encodeURI(), decodeURI(), encodeURIComponent() або decodeURIComponent() отримують некоректні дані.
decodeURIComponent("%");
// URIError: URI malformedEvalError, помилка при використанні eval(). У сучасних реалізаціях трапляється рідко. Спочатку її використовували, коли eval() застосовували некоректно.
throw new EvalError("Incorrect use of eval()");AggregateError, набір помилок. Виникає, коли одна операція повертає одразу кілька помилок, наприклад при Promise.any().
Promise.any([
Promise.reject(new Error("Error 1")),
Promise.reject(new Error("Error 2")),
]).catch(e => console.log(e.errors));Вивід:
[Error: Error 1, Error: Error 2]Власні помилки (Custom Errors)
Можна створювати власні класи помилок, успадковуючись від Error:
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
throw new ValidationError("Invalid email");Вивід:
ValidationError: Invalid emailТакий підхід дає змогу відрізняти доменні помилки від технічних прямо в catch, через if (e instanceof ValidationError).
Підсумкова таблиця
| Тип помилки | Коли виникає | Приклад |
|---|---|---|
| Error | Базовий клас для всіх помилок | throw new Error("Failure") |
| ReferenceError | Змінна не визначена | console.log(x) |
| TypeError | Невірний тип значення | null.toString() |
| RangeError | Значення поза допустимим діапазоном | new Array(-1) |
| SyntaxError | Помилка в синтаксисі | eval("if (true {") |
| URIError | Помилка кодування чи декодування URI | decodeURI("%") |
| EvalError | Помилка eval() (майже не використовується) | throw new EvalError() |
| AggregateError | Кілька помилок одразу | Promise.any([...]) |
Типові помилки
- Очікувати, що
try...catchспіймаєSyntaxErrorу власному файлі. Такий код не виконається взагалі, бо розбір відбувається раніше за виконання. - Ловити все одним
catch (e)і не дивитися наe.name. Без перевірки типу ви обробляєте помилку валідації так само, як збій мережі. - Забувати
super(message)у власному класі помилки. Тодіmessageбуде порожнім, а стек, неповним. - Плутати
ReferenceErrorіTypeError. Змінної немає взагалі, цеReferenceError; змінна є, але її значенняnullчиundefined, це вжеTypeError. - Покладатися на
EvalError. Сучасні рушії його майже не кидають, тому будувати логіку навколо нього не варто.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.