**Иерархия 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' должно логироваться в обоих случаях
Напишите функцию, принимающую массив и индекс. Если индекс выходит за границы, бросайте `RangeError`. Если аргумент не является массивом, бросайте `TypeError`.
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 с
Для активации режима слепого набора не подсматривайте на физическую клавиатуру.