Далее приводится более реалистичный пример инструкции try/catch. В нем вызываются метод factorial(), определенный в предыдущем разделе, и методы prompt() и alert() клиентского JavaScript для организации ввода и вывода:
try {
// Запросить число у пользователя
var n = Number(prompt("Введите положительное число",""));
// Вычислить факториал числа, предполагая, что входные данные корректны
var f = factorial(n);
// Вывести результат
alert(n + "! = " + f);
}
catch (ex) { // Если данные некорректны, управление будет передано сюда
alert(ех); // Сообщить пользователю об ошибке
}
Это пример инструкции try/catch без конструкции finally. Хотя finally используется не так часто, как catch, тем не менее иногда эта конструкция оказывается полезной. Однако ее поведение требует дополнительных объяснений. Блок finally гарантированно исполняется, если исполнялась хотя бы какая-то часть блока try, независимо от того, каким образом завершилось выполнение программного кода в блоке try. Эта возможность обычно используется для выполнения заключительных операций после выполнения программного кода в предложении try.
В обычной ситуации управление доходит до конца блока try, а затем переходит к блоку finally, который выполняет необходимые заключительные операции. Если управление вышло из блока try как результат выполнения инструкций return, continue или break, перед передачей управления в другое место выполняется блок finally.
Если в блоке try возникает исключение и имеется соответствующий блок catch для его обработки, управление сначала передается в блок catch, а затем - в блок finally. Если отсутствует локальный блок catch, то управление сначала передается в блок finally, а затем переходит на ближайший внешний блок catch, который может обработать исключение.
Если сам блок finally передает управление с помощью инструкции return, continue, break или throw или путем вызова метода, генерирующего исключение, незаконченная команда на передачу управления отменяется и выполняется новая. Например, если блок finally сгенерирует исключение, это исключение заменит любое ранее сгенерированное исключение. Если в блоке finally имеется инструкция return, произойдет нормальный выход из метода, даже если генерировалось исключение, которое не было обработано.
Конструкции try и finally могут использоваться вместе без конструкции сatch. В этом случае блок finally - это просто набор инструкций, выполняющих заключительные операции, который будет гарантированно выполнен независимо от наличия в блоке try инструкции break, continue или return. Напомню, из-за различий в работе инструкции continue в разных циклах невозможно написать цикл while, полностью имитирующий работу цикла for. Однако если добавить инструкцию try/finally, можно написать цикл while, который будет действовать точно так же, как цикл for, и корректно обрабатывать инструкцию continue:
// Имитация цикла for( инициализация ; проверка ; инкремент ) тело цикла;
инициализация ;
while( проверка ) {
try { тело цикла ; }
finally { инкремент ; }
}
Обратите однако внимание, что тело цикла while, содержащее инструкцию break, будет вести себя несколько иначе (из-за выполнения лишней операции инкремента перед выходом), чем тело цикла for, поэтому даже используя конструкцию finally, невозможно точно сымитировать цикл for с помощью цикла while.