Skip to main content

Типи помилок у 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.

Швидкий приклад

javascript
try { null.toString(); } catch (e) { console.log(e.name); // TypeError console.log(e.message); // Cannot read properties of null }

Error, базовий клас помилок

Це універсальний тип, від якого успадковуються всі інші помилки. Якщо ви не знаєте, який тип помилки підходить, можна використати просто Error.

javascript
throw new Error("Something went wrong");

Властивості об'єкта помилки:

  • name, ім'я помилки ("Error")
  • message, опис
  • stack, трасування стека, показує, де саме сталася помилка

Помилки часу виконання: ReferenceError, TypeError, RangeError

ReferenceError, помилка посилання. Виникає, коли відбувається звертання до неіснуючої змінної або до властивості, недоступної в поточній області видимості.

javascript
console.log(x); // ReferenceError: x is not defined

Також може виникати при неправильному використанні this.

TypeError, помилка типу. Стається, коли операцію застосовують до значення невідповідного типу або намагаються викликати те, що не є функцією.

javascript
let n = null; console.log(n.toString()); // TypeError: Cannot read properties of null
javascript
let func = 123; func(); // TypeError: func is not a function

RangeError, вихід за допустимі межі. Виникає, коли передане значення поза допустимим діапазоном.

javascript
new Array(-5); // RangeError: Invalid array length
javascript
(123.456).toFixed(200); // RangeError: toFixed() digits argument must be between 0 and 100

SyntaxError, URIError, EvalError і AggregateError

SyntaxError, синтаксична помилка. Помилка при порушенні синтаксису JavaScript. Рушій не може розібрати код, тому програма навіть не запускається.

javascript
eval("if (true { console.log('hi'); }"); // SyntaxError: Unexpected token '{'

Такі помилки не можна спіймати через try...catch, бо вони стаються до початку виконання. Виняток, це код, який парситься окремо і пізніше, як у прикладі з eval вище або у new Function(...).

URIError, помилка в URI-функціях. Стається, якщо функції encodeURI(), decodeURI(), encodeURIComponent() або decodeURIComponent() отримують некоректні дані.

javascript
decodeURIComponent("%"); // URIError: URI malformed

EvalError, помилка при використанні eval(). У сучасних реалізаціях трапляється рідко. Спочатку її використовували, коли eval() застосовували некоректно.

javascript
throw new EvalError("Incorrect use of eval()");

AggregateError, набір помилок. Виникає, коли одна операція повертає одразу кілька помилок, наприклад при Promise.any().

javascript
Promise.any([ Promise.reject(new Error("Error 1")), Promise.reject(new Error("Error 2")), ]).catch(e => console.log(e.errors));

Вивід:

text
[Error: Error 1, Error: Error 2]

Власні помилки (Custom Errors)

Можна створювати власні класи помилок, успадковуючись від Error:

javascript
class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; } } throw new ValidationError("Invalid email");

Вивід:

text
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Помилка кодування чи декодування URIdecodeURI("%")
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. Сучасні рушії його майже не кидають, тому будувати логіку навколо нього не варто.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.