> context = newContext;
> var result = body();
> context = oldContext;
> return result;
>}
Что, если функция >body
выбросит исключение? В таком случае вызов >withContext
будет выброшен исключением из стека, и переменной >context
никогда не будет возвращено первоначальное значение.
Но у инструкции >try
есть ещё одна особенность. За ней может следовать блок >finally
, либо вместо >catch
, либо вместе с >catch
. Блок >finally
означает «выполнить код в любом случае после выполнения блока >try
». Если функции надо что-то подчистить, то подчищающий код нужно включать в блок >finally
.
>function withContext(newContext, body) {
> var oldContext = context;
> context = newContext;
> try {
> return body();
> } finally {
> context = oldContext;
> }
>}
Заметьте, что нам больше не нужно сохранять результат вызова >body
в отдельной переменной, чтобы вернуть его. Даже если мы возвращаемся из блока >try
, блок >finally
всё равно будет выполнен. Теперь мы можем безопасно сделать так:
>try {
> withContext(5, function() {
> if (context < 10)
> throw new Error("Контекст слишком мал!");
> });
>} catch (e) {
> console.log("Игнорируем: " + e);
>}
>// → Игнорируем: Error: Контекст слишком мал!
>console.log(context);
>// → null
Несмотря на то, что вызываемая из >withContext
функция «сломалась», сам по себе >withContext
по-прежнему подчищает значение переменной >context
.
Выборочный отлов исключений
Когда исключение доходит до низа стека и его никто не поймал, его обрабатывает окружение. Как именно – зависит от конкретного окружения. В браузерах описание ошибки выдаётся в консоль (она обычно доступна в меню «Инструменты» или «Разработка»).
Если речь идёт об ошибках или проблемах, которые программа не может обработать в принципе, допустимо просто пропустить такую ошибку. Необработанное исключение – разумный способ сообщить о проблеме в программе, и консоль в современных браузерах выдаст вам необходимую информацию о том, какие вызовы функций были в стеке в момент возникновения проблемы.
Если возникновение проблемы предсказуемо, программа не должна падать с необработанным исключением – это не очень дружественно по отношению к пользователю.
Недопустимое использование языка – ссылки на несуществующую переменную, запрос свойств у переменной, равной >null
, или вызов чего-то, что не является функцией – тоже приводит к выбрасыванию исключений. Такие исключения можно отлавливать точно так же, как свои собственные.
При входе в блок >catch
мы знаем только, что что-то внутри блока >try
привело к исключению. Мы не знаем, что именно, и какое исключение произошло.