6.17 try/catch/finally
The try/catch/finally
statement is
JavaScript's exception-handling mechanism. The
try clause of this statement simply defines the
block of code whose exceptions are to be handled. The
try block is followed by a
catch clause, which is
a block of statements that are invoked when an exception occurs
anywhere within the try block. The
catch clause is followed by a
finally block containing cleanup code that
is guaranteed to be executed, regardless of what happens in the
try block. Both the catch and
finally blocks are optional, but a
try block must be accompanied by at least one of
these blocks. The try, catch,
and finally blocks all begin and end with curly
braces. These are a required part of the syntax and cannot be
omitted, even if the clause contains only a single statement. Like
the throw statement, the
try/catch/finally statement is standardized by
ECMAScript v3 and implemented in JavaScript 1.4.
The following code illustrates the syntax and purpose of the
try/catch/finally statement. In particular, note
that the catch
keyword
is followed by an identifier in parentheses. This identifier is like
a function argument. It names a local variable that exists only
within the body of the catch block. JavaScript
assigns whatever exception object or value was thrown to this
variable:
try {
// Normally, this code runs from the top of the block to the bottom
// without problems. But it can sometimes throw an exception,
// either directly, with a throw statement, or indirectly, by calling
// a method that throws an exception.
}
catch (e) {
// The statements in this block are executed if, and only if, the try
// block throws an exception. These statements can use the local variable
// e to refer to the Error object or other value that was thrown.
// This block may handle the exception somehow, or it may ignore the
// exception by doing nothing, or it may rethrow the exception with throw.
}
finally {
// This block contains statements that are always executed, regardless of
// what happens in the try block. They are executed whether the try
// block terminates:
// 1) normally, after reaching the bottom of the block
// 2) because of a break, continue, or return statement
// 3) with an exception that is handled by a catch clause above
// 4) with an uncaught exception that is still propagating
}
Here is a more realistic example of the
try/catch
statement. It uses the factorial(
) method defined in the previous section
and the client-side JavaScript methods prompt(
)
and alert( ) for
input and output:
try {
// Ask the user to enter a number
var n = prompt("Please enter a positive integer", "");
// Compute the factorial of the number, assuming that the user's
// input is valid
var f = factorial(n);
// Display the result
alert(n + "! = " + f);
}
catch (ex) { // If the user's input was not valid, we end up here
// Tell the user what the error is
alert(ex);
}
This example is a try/catch statement with no
finally clause. Although
finally is not used as often as
catch, it can often be useful. However, its
behavior requires additional explanation. The
finally clause is guaranteed to be executed if any
portion of the try block is executed, regardless
of how the code in the try block completes. It is
generally used to clean up after the code in the
try clause.
In the normal case, control reaches the end of the
try block and then proceeds to the
finally block, which performs any necessary
cleanup. If control leaves the try block because
of a return, continue, or
break statement, the finally
block is executed before control transfers to its new destination.
If an exception occurs in the try block and there
is an associated catch block to handle the
exception, control transfers first to the catch
block and then to the finally block. If there is
no local catch block to handle the exception,
control transfers first to the finally block and
then propagates up to the nearest containing catch
clause that can handle the exception.
If a finally block itself transfers control with a
return, continue,
break, or throw statement, or
by calling a method that throws an exception, the pending control
transfer is abandoned and this new transfer is processed. For
example, if a finally clause throws an exception,
that exception replaces any exception that was in the process of
being thrown. If a finally clause issues a
return statement, the method returns normally,
even if an exception has been thrown and has not yet been handled.
try
and finally can be used together without a
catch clause. In this case, the
finally block is simply cleanup code that is
guaranteed to be executed, regardless of any
break, continue, or
return statements within the
try clause. For example, the following code uses a
try/finally statement to ensure that a loop
counter variable is incremented at the end of each iteration, even
when an iteration terminates abruptly because of a
continue statement:
var i = 0, total = 0;
while(i < a.length) {
try {
if ((typeof a[i] != "number") || isNaN(a[i])) // If it is not a number,
continue; // go on to the next iteration of the loop.
total += a[i]; // Otherwise, add the number to the total.
}
finally {
i++; // Always increment i, even if we used continue above.
}
}
|