Тест: Продвинутое владение ошибками JS
Ваши исключения действительно исключительные?
Считаешь, что знаешь ошибки JavaScript досконально?
- Проверь свои навыки обработки ошибок! 💥
- Регистрация не нужна. ✨
- Выбор из нескольких вариантов. 🤖 … Это не обычные вопросы про try‑catch!
Что возвращает JSON.stringify(error)?
const error = new Error('Oops');console.log(JSON.stringify(error));Объекты Error имеют неперечислимые свойства (message, name, stack), поэтому JSON.stringify() возвращает {}. Это распространённый подводный камень при отправке ошибок в ответах API. Используйте JSON.stringify(error, Object.getOwnPropertyNames(error)) или создайте обычный объект вместо него.
В чём разница между этими двумя?
const err = new Error('Test');console.log(err);console.log(JSON.stringify(err));console.log(err) показывает ошибку с её сообщением и трассировкой стека, потому что консоль имеет специальную обработку объектов Error. JSON.stringify(err) возвращает '{}', так как свойства Error не перечисляемы. Эта разница сбивает с толку многих разработчиков, отлаживающих API.
Каковы результаты этих проверок?
class CustomError extends Error {}const err = new CustomError('test');
console.log(err instanceof CustomError);console.log(err instanceof Error);console.log(err instanceof Object);Все три возвращают true. CustomError наследует Error, который наследует Object. Оператор instanceof проверяет всю цепочку прототипов, поэтому экземпляр CustomError также является экземпляром Error и Object.
Что происходит с instanceof Error между iframe‑ами?
// In iframe:const iframeError = new Error('test');// In parent window:console.log(iframeError instanceof Error);instanceof может возвращать false в разных контекстах выполнения (iframe‑ы, воркеры), потому что каждый контекст имеет собственный конструктор Error. Используйте Object.prototype.toString.call(obj) === '[object Error]' для надёжного определения ошибки в разных контекстах.
Что происходит, когда вы бросаете строку?
try { throw "Oops!";} catch (e) { console.log(e instanceof Error); console.log(typeof e);}JavaScript позволяет бросать любое значение. Здесь e instanceof Error равно false, а typeof e — "string". Это может сломать код обработки ошибок, который предполагает, что все пойманные исключения являются объектами Error. Всегда бросайте экземпляры Error для лучшей отладки.
Каково значение err.name?
class CustomError extends Error { constructor(message) { super(message); this.name = this.constructor.name; }}const err = new CustomError('test');console.log(err.name);err.name равно "CustomError", потому что this.constructor.name возвращает имя класса. Установка this.name = this.constructor.name — распространённый приём, чтобы пользовательские классы ошибок показывали правильное имя в трассировках стека и сообщениях об ошибке.
Что будет выведено, если не установить name?
class MyError extends Error { // No constructor or name setting}const err = new MyError('test');console.log(err.name);Если явно не задать this.name, ошибка наследует свойство name по умолчанию из класса Error, которое равно "Error". Поэтому в пользовательских классах ошибок всегда следует устанавливать this.name = this.constructor.name в конструкторе.
Что возвращает wrapper.cause.message?
const original = new Error('Original error');const wrapper = new Error('Wrapper', { cause: original });console.log(wrapper.cause.message);Error.cause (ES2022) позволяет цепочкой связывать ошибки, сохраняя исходный контекст ошибки. wrapper.cause ссылается на исходную ошибку, поэтому wrapper.cause.message возвращает "Original error". Это полезно для оборачивания ошибок нижнего уровня в контекст более высокого уровня.
Что делает Error.captureStackTrace?
function createError(msg) { const err = new Error(msg); Error.captureStackTrace(err, createError); return err;}const error = createError('test');Error.captureStackTrace (V8/Node.js) удаляет указанную функцию (createError) из трассировки стека, делая функции‑фабрики ошибок невидимыми для конечных пользователей. Это создаёт более чистые трассировки стека, указывающие на место вызова фабрики, а не на саму фабрику.
Каково сообщение об ошибке?
function validate(value) { if (!value) { throw new Error( `Value ${value} is invalid` ); }}try { validate(undefined);} catch (e) { console.log(e.message);}Шаблонные строки преобразуют undefined в строку "undefined" при интерполяции. Сообщение об ошибке становится "Value undefined is invalid". Для более чистых сообщений рекомендуется использовать value ?? 'null' или аналогичные проверки перед интерполяцией.
Что отправляется клиенту?
// Express.js routeapp.get('/api/data', (req, res) => { const error = new Error('Database failed'); res.json({ error });});res.json() использует JSON.stringify() внутри, поэтому объект Error превращается в {}. Клиент получает {"error":{}}. Чтобы исправить, используйте res.json({ error: error.message }) или res.json({ error: { message: error.message, name: error.name } }).
Что может принимать Promise.reject()?
Promise.reject('string').catch(e => console.log(typeof e));Promise.reject({code: 404}).catch(e => console.log(e.code));Promise.reject(42).catch(e => console.log(e));Как и throw, Promise.reject() принимает любое значение — строки, объекты, числа и т.д. Это выводит "string", 404 и 42. Всегда проверяйте тип перехваченных значений в цепочках промисов, особенно при работе с кодом сторонних библиотек, который может отклонять не объектами Error.
Насколько надёжны error.code и error.errno?
const fs = require('fs');fs.readFile('missing.txt', (err, data) => { if (err) { console.log(err.code); // 'ENOENT' console.log(err.errno); // -2 }});Свойства вроде code и errno зависят от среды (в данном случае Node.js) и не входят в стандартный объект Error. Ошибки в браузере этих свойств не имеют. Всегда проверяйте их наличие: if (err.code === 'ENOENT') вместо того, чтобы полагаться на их существование.
Что возвращают эти проверки?
const fakeError = { name: 'Error', message: 'Fake error', stack: 'fake stack'};
console.log(fakeError instanceof Error);console.log(Object.prototype.toString.call( fakeError) === '[object Error]');instanceof Error возвращает false, потому что объект не был создан конструктором Error. Object.prototype.toString.call() также возвращает false (он возвращает '[object Object]') потому что проверяет внутренний слот [[Class]]. Оба метода правильно определяют, что это поддельный объект ошибки.
Овладейте искусством обработки ошибок
От подводных камней сериализации до сбоев instanceof в разных контекстах — эти продвинутые темы отделяют новичков от изношенных профессионалов.
Готовы к новым задачам? Загляните в нашу полную коллекцию викторин для дополнительных головоломок по JavaScript, алгоритмам и не только!