**Ієрархія Error**
Кожна кинута помилка в JavaScript є (або повинна бути) екземпляром `Error` або одного з його підкласів:
```javascript
Error // базовий клас — використовується для кастомних помилок
├── SyntaxError // невалідний синтаксис JS (зазвичай при парсингу)
├── ReferenceError // змінна не знайдена
├── TypeError // неправильний тип для операції
├── RangeError // значення поза допустимим діапазоном
├── URIError // неправильний URI
└── EvalError // помилка всередині eval() (рідко зустрічається)
```
**Створення та кидання помилок**
```javascript
throw new Error('Щось пішло не так'); // загальна
throw new TypeError('Очікується рядок'); // конкретна
throw new RangeError('Індекс поза межами'); // конкретна
// Можна кидати що завгодно, але об'єкт Error дає стек викликів:
throw 'oops'; // працює, але втрачає стек — уникай цього
throw { code: 404 }; // та сама проблема — використовуй new Error()
```
**Властивості Error**
```javascript
try {
null.property; // TypeError
} catch (err) {
console.log(err.name); // 'TypeError'
console.log(err.message); // "Cannot read properties of null (reading 'property')"
console.log(err.stack);
// TypeError: Cannot read properties of null (reading 'property')
// at <anonymous>:2:8
// at ...
}
```
`err.stack` — рядок з повідомленням про помилку та стеком викликів — незамінний для дебагінгу. Не є частиною специфікації, але всі основні двигуни його надають.
**err.name vs constructor.name**
```javascript
const e = new TypeError('bad');
e.name === 'TypeError' // true — мітка типу помилки
e.constructor.name === 'TypeError' // теж true — але тільки якщо клас не мініфікований
// Краще перевіряти err.name або instanceof у catch-блоках:
if (err instanceof TypeError) { ... } // найчистіше
if (err.name === 'TypeError') { ... } // теж добре
// Не покладайся на err.constructor.name у production (мініфікація може змінити)
```
**Кастомні класи помилок**
```javascript
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError'; // перевизначити — важливо!
this.field = field;
}
}
throw new ValidationError('Обов\'язкове поле відсутнє', 'email');
// У catch:
if (err instanceof ValidationError) {
console.log(`Поле '${err.field}': ${err.message}`);
}
```
Завжди встановлюй `this.name` у кастомних підкласах — інакше `err.name` успадкує 'Error' від базового класу, що ламає перевірку типу за рядком.
try/catch/finally, перекидання та необроблені відхилення промісів
Напишіть блок `try/catch/finally`, що розбирає рядок JSON. Якщо розбір не вдається, поверніть значення за замовчуванням `{}`. Блок `finally` повинен логувати 'parse attempted'.
function safeParse(str) {
// ваш код тут
}
console.log(safeParse('{"a":1}')); // { a: 1 }
console.log(safeParse('invalid')); // {}
// 'parse attempted' повинно логуватися в обох випадках
function getElement(arr, index) {
if (!Array.isArray(arr)) throw new TypeError('Expected an array');
if (index < 0 || index >= arr.length) throw new RangeError(`Index ${index} out of bounds`);
return arr[index];
}
Обробіть асинхронні помилки: напишіть асинхронну функцію, що завантажує URL (симульований). Якщо завантаження не вдається, логуйте повідомлення про помилку і поверніть null.
async function simulatedFetch(url) {
if (!url.startsWith('https')) throw new Error(`Invalid URL: ${url}`);
return { status: 200, data: 'ok' };
}
async function safeFetch(url) {
// ваш код тут
}
safeFetch('https://example.com').then(console.log); // { status: 200, data: 'ok' }
safeFetch('http://bad.com').then(console.log); // null (та логує помилку)
Напишіть функцію, що обгортає іншу функцію і перехоплює будь-який TypeError, повертаючи натомість значення за замовчуванням. Інші типи помилок повинні поширюватися нормально.
function withTypeErrorFallback(fn, defaultValue) {
// ваш код тут
}
const safe = withTypeErrorFallback(() => null.length, 0);
console.log(safe); // 0
try {
withTypeErrorFallback(() => { throw new RangeError('oops'); }, 0);
} catch (e) {
console.log(e instanceof RangeError); // true
}
Рішення
function withTypeErrorFallback(fn, defaultValue) {
try {
return fn();
} catch (e) {
if (e instanceof TypeError) return defaultValue;
throw e;
}
}
Реалізуйте ланцюжок помилок: створіть функцію, що обгортає низькорівневу помилку у високорівневу, зберігаючи оригінальну помилку як `cause`.
function readConfig(filename) {
throw new Error(`File not found: ${filename}`);
}
function loadApp(configPath) {
// Спробуйте readConfig(configPath). Якщо не вдається, кидайте новий Error
// 'Failed to load application' з оригіналом як 'cause'
}
try {
loadApp('config.json');
} catch (e) {
console.log(e.message); // 'Failed to load application'
console.log(e.cause.message); // 'File not found: config.json'
}
Рішення
function readConfig(filename) {
throw new Error(`File not found: ${filename}`);
}
function loadApp(configPath) {
try {
return readConfig(configPath);
} catch (e) {
throw new Error('Failed to load application', { cause: e });
}
}
Напишіть функцію `assertType`, що кидає `TypeError` з описовим повідомленням, якщо значення не є очікуваного типу (перевіряється через `typeof`).
function assertType(value, expectedType) {
// ваш код тут
}
assertType(42, 'number'); // ok, не кидає
assertType('hello', 'string'); // ok
try {
assertType(42, 'string');
} catch (e) {
console.log(e instanceof TypeError); // true
console.log(e.message); // наприклад 'Expected string, got number'
}
Рішення
function assertType(value, expectedType) {
const actual = typeof value;
if (actual !== expectedType) {
throw new TypeError(`Expected ${expectedType}, got ${actual}`);
}
}
No split tab
Налаштування cookies
Ми використовуємо необхідні cookies для роботи сайту. З вашого дозволу ми також можемо зберігати налаштування сайту та використовувати аналітичні й рекламні cookies, щоб розуміти використання сайту й підтримувати розвиток проєкту.
* Ви завжди можете змінити свій вибір у налаштуваннях сайту.
Оберіть категорії cookies
Налаштування аналітики
Можна вимкнути аналітику використання платформи. Також можна надіслати в Google Analytics запит на видалення даних про використання цього сайту, пов'язаних із цим браузером.
Навчальний workspace
Навчайтеся, читаючи, запускаючи код і розв'язуючи задачі.
Практикуйте програмування з поясненнями тем, вправами, інструментами browser IDE, перевіркою regex і тренуванням друку коду в одному workspace.
Відкривайте інструменти у вкладках.Вправи, IDE-інструменти й тренажери залишаються доступними як вкладки сайту.
Перемикайтеся без втрати контексту.Переходьте між поясненнями, кодом та утилітами, зберігаючи своє місце.
Використовуйте sidebar як карту.Ліві панелі містять навігацію, налаштування, файли, libraries та керування інструментами.
PythonJavaScriptSQLite
Одна IDE, три практичні режими
Python у браузері.Запускайте невеликі скрипти, пробуйте бібліотеки й тренуйте API-запити без встановлення.
JavaScript для швидких експериментів.Перевіряйте код для браузера й порівнюйте ідеї поруч із навчальними матеріалами.
SQLite для практики з даними.Відкривайте оглядач бази даних, переглядайте таблиці, пишіть запити й вивчайте SQL локально.
ТемаIDE
Працюйте поруч у split tabs
Тримайте інструкції перед очима.Відкрийте вправу або довідкову сторінку поруч з IDE, замість постійних перемикань.
Порівнюйте інструменти під час навчання.Розміщуйте перевірки regex, пояснення та експерименти з кодом поруч, коли це потрібно для задачі.
Закрийте split, коли завершите.Workspace повернеться до однієї сфокусованої вкладки, а відкриті вкладки сайту залишаться доступними.
Тренажер друку коду
Або звичайного тексту
Тренажер розрахований на фізичну клавіатуру.Відкрийте цей розділ на ноутбуці або комп'ютері з широким екраном. На телефоні тренування друку не працюватиме коректно.
Швидкість: 0 зн/хв
0 слів/хв
Найкраща швидкість (60с): 0 зн/хв
0 слів/хв
Помилки: 0
Загальний час: 0.0 с
Щоб тренувати сліпий друк, не підглядайте на фізичну клавіатуру.