Какова разница между `throw new Error` и `throw someObject`?
Я хочу написать общий обработчик ошибок, который будет перехватывать кастомные ошибки, выбрасываемые намеренно в любом месте кода.
Когда я выполнил следующий код:
try {
throw new Error({'hehe':'haha'});
// throw new Error('hehe');
} catch(e) {
alert(e);
console.log(e);
}
Лог в Firefox показывает: Error: [object Object]
, и я не смог разобрать объект.
Для второго варианта с throw
лог показывает: Error: hehe
.
Однако, когда я выполнил следующий код:
try {
throw ({'hehe':'haha'});
} catch(e) {
alert(e);
console.log(e);
}
Консоль показала: Object { hehe="haha"}
, благодаря чему я смог получить доступ к свойствам ошибки.
В чем разница?
Разница действительно заключается в том, что в первом случае я выбрасываю объект ошибки, а во втором — просто объект? В первом случае строка просто передается как строка, а объект — как объект, но синтаксис отличается?
Я не исследовал, как выбрасывать объект ошибки... Я использовал только выброс строк.
Есть ли другие способы, кроме вышеупомянутых двух?
5 ответ(ов)
throw "I'm Evil"
Использование throw
прервёт дальнейшее выполнение и передаст строку сообщения при поймании ошибки.
try {
throw "I'm Evil"
console.log("Вы никогда не дойдете до меня", 123465)
} catch (e) {
console.log(e); // I'm Evil
}
Консоль после throw никогда не будет достигнута из-за прерывания выполнения.
throw new Error("I'm Evil")
Использование throw new Error
создает событие ошибки с двумя параметрами: name и message. Это также прерывает дальнейшее выполнение.
try {
throw new Error("I'm Evil")
console.log("Вы никогда не дойдете до меня", 123465)
} catch (e) {
console.log(e.name, e.message); // Error I'm Evil
}
throw Error("I'm Evil")
И для полноты картины, этот вариант тоже работает, хотя технически это не самый правильный способ:
try {
throw Error("I'm Evil")
console.log("Вы никогда не дойдете до меня", 123465)
} catch (e) {
console.log(e.name, e.message); // Error I'm Evil
}
console.log(typeof(new Error("hello"))); // object
console.log(typeof(Error)); // function
Таким образом, использование throw
может быть разным, в зависимости от ваших целей и контекста. Рекомендуется использовать throw new Error
, так как это предоставляет больше информации о возникшей ошибке.
Возможно, следующая статья более подробно рассматривает вопрос о том, что лучше использовать: throw 'An error'
или throw new Error('An error')
:
http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/
В статье утверждается, что использование new Error()
более надежно, так как такие браузеры, как Internet Explorer и Safari (неясно, для каких версий), не корректно отображают сообщение об ошибке при использовании первого варианта.
В статье говорится:
Если использовать
throw 'An error'
, это приведет к выбросу ошибки, но не все браузеры будут работать так, как вы ожидаете. Firefox, Opera и Chrome отображают сообщение об "необработанном исключении" и включают строку с сообщением. Safari и Internet Explorer просто выбрасывают ошибку "необработанное исключение" и не предоставляют строку с сообщением вообще. Явно, это не оптимально с точки зрения отладки.
Таким образом, в контексте отладки и кросс-браузерной совместимости, рекомендуется использовать throw new Error()
.
TLDR: Они эквивалентны: Error(x) === new Error(x)
.
// Это:
const x = Error('Я создан с помощью вызова функции!');
// Имеет такую же функциональность, как и это:
const y = new Error('Я сконструирован через ключевое слово "new"!');
Источник: MDN Web Docs
throw
и throw Error
функционально эквивалентны. Однако, когда вы их ловите и сериализуете с помощью console.log
, они сериализуются не совсем одинаково:
throw 'Параметр не является числом!';
throw new Error('Параметр не является числом!');
throw Error('Параметр не является числом!');
Console.log(e)
для приведённого выше кода выдаст 2 разных результата:
Параметр не является числом!
Error: Параметр не является числом!
Error: Параметр не является числом!
Таким образом, хотя поведение Error
и new Error
идентично, обработка и отображение этих значений при выбросе ошибки может выглядеть по-разному.
Вы сначала упоминаете этот код:
throw new Error('sample');
а затем в вашем первом примере пишете:
throw new Error({'hehe':'haha'});
Первый объект ошибки действительно будет полезен, потому что он ожидает строковое значение, в данном случае 'sample'. Второй пример не будет полезен, поскольку вы пытаетесь передать объект, а он ожидает строку, что не позволит отобразить удачное сообщение об ошибке.
В объекте ошибки будет свойство "message", которое будет равно 'sample'.
Вы можете использовать конструкцию throw
для выброса объектов, как показано ниже:
throw ({message: 'Это не удалось'})
Тогда, например, в вашем блоке try/catch
:
try {
// Ваш код
} catch(e) {
console.log(e); // {message: 'Это не удалось'}
console.log(e.message); // Это не удалось
}
Также вы можете просто выбросить строковое сообщение об ошибке:
throw ('Ваша ошибка')
try {
// Ваш код
} catch(e) {
console.log(e); // Ваша ошибка
}
А если вы хотите использовать стандартный класс ошибки, вы можете сделать так:
throw new Error('Сообщение об ошибке'); // принимает только строку
Обратите внимание, что при вызове new Error
необходимо передавать строку в качестве аргумента.
Длина объекта в JavaScript
Преобразование объекта JS в строку JSON
Как проверить наличие ключа в объекте JavaScript?
Как удалить все дубликаты из массива объектов?
Как получить подмножество свойств объекта JavaScript?