JavaScript (что является вопиющим упущением) не предоставляет непосредственной поддержки выборочного отлова исключений: либо ловим все, либо никакие. Из-за этого люди часто предполагают, что случившееся исключение – именно то, ради которого и писался блок >catch
.
Но может быть и по-другому. Нарушение произошло где-то ещё, или в программу вкралась ошибка. Вот пример, где мы пробуем вызывать >promptDirection
до тех пор, пока не получим допустимый ответ:
>for (;;) {
> try {
> var dir = promtDirection("Куда?"); // ← опечатка!
> console.log("Ваш выбор", dir);
> break;
> } catch (e) {
> console.log("Недопустимое направление. Попробуйте ещё раз.");
> }
>}
Конструкция >for (;;)
– способ устроить бесконечный цикл. Мы вываливаемся из него, только когда получаем допустимое направление. Но мы неправильно написали название >promptDirection
, что приводит к ошибке “undefined variable”. А так как блок >catch
игнорирует значение исключения >e
, предполагая, что он разбирается с другой проблемой, он считает, что выброшенное исключение является результатом неправильных входных данных. Это приводит к бесконечному циклу и скрывает полезное сообщение об ошибке насчёт неправильного имени переменной.
Как правило, не стоит так ловить исключения, если только у вас нет цели перенаправить их куда-либо – к примеру, по сети, чтобы сообщить другой системе о падении нашей программы. И даже тогда внимательно смотрите, не будет ли скрыта важная информация.
Значит, нам надо поймать определённое исключение. Мы можем в блоке >catch
проверять, является ли случившееся исключение интересующим нас исключением, а в противном случае заново выбрасывать его. Но как нам распознать исключение?
Конечно, мы могли бы сравнить свойство >message
с сообщением об ошибке, которую мы ждём. Но это ненадёжный способ писать код – использовать информацию, предназначающуюся для человека (сообщение), чтобы принять программное решение. Как только кто-нибудь поменяет или переведёт это сообщение, код перестанет работать.
Давайте лучше определим новый тип ошибки и используем >instanceof
для его распознавания.
>function InputError(message) {
> this.message = message;
> this.stack = (new Error()).stack;
>}
>InputError.prototype = Object.create(Error.prototype);
>InputError.prototype.name = "InputError";
Прототип наследуется от >Error.prototype
, поэтому >instanceof Error
тоже будет выполняться для объектов типа >InputError
. И ему назначено свойство >name
, как и другим стандартным типам ошибок (>Error
, >SyntaxError
, >ReferenceError
, и т. п.)
Присвоение свойству