File size: 10,780 Bytes
780c9fe |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
---
title: try...catch
slug: Web/JavaScript/Reference/Statements/try...catch
page-type: javascript-statement
browser-compat: javascript.statements.try_catch
sidebar: jssidebar
---
The **`try...catch`** statement is comprised of a `try` block and either a `catch` block, a `finally` block, or both. The code in the `try` block is executed first, and if it throws an exception, the code in the `catch` block will be executed. The code in the `finally` block will always be executed before control flow exits the entire construct.
{{InteractiveExample("JavaScript Demo: try...catch statement")}}
```js interactive-example
try {
nonExistentFunction();
} catch (error) {
console.error(error);
// Expected output: ReferenceError: nonExistentFunction is not defined
// (Note: the exact output may be browser-dependent)
}
```
## Syntax
```js-nolint
try {
tryStatements
} catch (exceptionVar) {
catchStatements
} finally {
finallyStatements
}
```
- `tryStatements`
- : The statements to be executed.
- `catchStatements`
- : Statement that is executed if an exception is thrown in the `try` block.
- `exceptionVar` {{optional_inline}}
- : An optional [identifier or pattern](#catch_binding) to hold the caught exception for the associated `catch` block. If the `catch` block does not use the exception's value, you can omit the `exceptionVar` and its surrounding parentheses.
- `finallyStatements`
- : Statements that are executed before control flow exits the `try...catch...finally` construct. These statements execute regardless of whether an exception was thrown or caught.
## Description
The `try` statement always starts with a `try` block. Then, a `catch` block or a `finally` block must be present. It's also possible to have both `catch` and `finally` blocks. This gives us three forms for the `try` statement:
- `try...catch`
- `try...finally`
- `try...catch...finally`
Unlike other constructs such as [`if`](/en-US/docs/Web/JavaScript/Reference/Statements/if...else) or [`for`](/en-US/docs/Web/JavaScript/Reference/Statements/for), the `try`, `catch`, and `finally` blocks must be _blocks_, instead of single statements.
```js-nolint example-bad
try doSomething(); // SyntaxError
catch (e) console.log(e);
```
A `catch` block contains statements that specify what to do if an exception is thrown in the `try` block. If any statement within the `try` block (or in a function called from within the `try` block) throws an exception, control is immediately shifted to the `catch` block. If no exception is thrown in the `try` block, the `catch` block is skipped.
The `finally` block will always execute before control flow exits the `try...catch...finally` construct. It always executes, regardless of whether an exception was thrown or caught.
You can nest one or more `try` statements. If an inner `try` statement does not have a `catch` block, the enclosing `try` statement's `catch` block is used instead.
You can also use the `try` statement to handle JavaScript exceptions. See the [JavaScript Guide](/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#exception_handling_statements) for more information on JavaScript exceptions.
### Catch binding
When an exception is thrown in the `try` block, `exceptionVar` (i.e., the `e` in `catch (e)`) holds the exception value. You can use this {{Glossary("binding")}} to get information about the exception that was thrown. This {{Glossary("binding")}} is only available in the `catch` block's {{Glossary("Scope", "scope")}}.
It doesn't need to be a single identifier. You can use a [destructuring pattern](/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring) to assign multiple identifiers at once.
```js
try {
throw new TypeError("oops");
} catch ({ name, message }) {
console.log(name); // "TypeError"
console.log(message); // "oops"
}
```
The bindings created by the `catch` clause live in the same scope as the `catch` block, so any variables declared in the `catch` block cannot have the same name as the bindings created by the `catch` clause. (There's [one exception to this rule](/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features#statements), but it's a deprecated syntax.)
```js-nolint example-bad
try {
throw new TypeError("oops");
} catch ({ name, message }) {
var name; // SyntaxError: Identifier 'name' has already been declared
let message; // SyntaxError: Identifier 'message' has already been declared
}
```
The exception binding is writable. For example, you may want to normalize the exception value to make sure it's an {{jsxref("Error")}} object.
```js
try {
throw "Oops; this is not an Error object";
} catch (e) {
if (!(e instanceof Error)) {
e = new Error(e);
}
console.error(e.message);
}
```
If you don't need the exception value, you can omit it along with the enclosing parentheses.
```js
function isValidJSON(text) {
try {
JSON.parse(text);
return true;
} catch {
return false;
}
}
```
### The finally block
The `finally` block contains statements to execute after the `try` block and `catch` block(s) execute, but before the statements following the `try...catch...finally` block. Control flow will always enter the `finally` block, which can proceed in one of the following ways:
- Immediately after the `try` block finishes execution normally (and no exceptions were thrown);
- Immediately after the `catch` block finishes execution normally;
- Immediately before the execution of a control-flow statement (`return`, `throw`, `break`, `continue`) in the `try` block or `catch` block that would exit the block.
If an exception is thrown from the `try` block, even when there's no `catch` block to handle the exception, the `finally` block still executes, in which case the exception is still thrown immediately after the `finally` block finishes executing.
The following example shows one use case for the `finally` block. The code opens a file and then executes statements that use the file; the `finally` block makes sure the file always closes after it is used even if an exception was thrown.
```js
openMyFile();
try {
// tie up a resource
writeMyFile(theData);
} finally {
closeMyFile(); // always close the resource
}
```
Control flow statements (`return`, `throw`, `break`, `continue`) in the `finally` block will "mask" any completion value of the `try` block or `catch` block. In this example, the `try` block tries to return 1, but before returning, the control flow is yielded to the `finally` block first, so the `finally` block's return value is returned instead.
```js
function doIt() {
try {
return 1;
} finally {
return 2;
}
}
doIt(); // returns 2
```
It is generally a bad idea to have control flow statements in the `finally` block. Only use it for cleanup code.
## Examples
### Unconditional catch block
When a `catch` block is used, the `catch` block is executed when any exception is thrown from within the `try` block. For example, when the exception occurs in the following code, control transfers to the `catch` block.
```js
try {
throw new Error("My exception"); // generates an exception
} catch (e) {
// statements to handle any exceptions
logMyErrors(e); // pass exception object to error handler
}
```
The `catch` block specifies an identifier (`e` in the example above) that holds the value of the exception; this value is only available in the {{Glossary("Scope", "scope")}} of the `catch` block.
### Conditional catch blocks
You can create "Conditional `catch` blocks" by combining `try...catch` blocks with `if...else if...else` structures, like this:
```js
try {
myRoutine(); // may throw three types of exceptions
} catch (e) {
if (e instanceof TypeError) {
// statements to handle TypeError exceptions
} else if (e instanceof RangeError) {
// statements to handle RangeError exceptions
} else if (e instanceof EvalError) {
// statements to handle EvalError exceptions
} else {
// statements to handle any unspecified exceptions
logMyErrors(e); // pass exception object to error handler
}
}
```
A common use case for this is to only catch (and silence) a small subset of expected errors, and then re-throw the error in other cases:
```js
try {
myRoutine();
} catch (e) {
if (e instanceof RangeError) {
// statements to handle this very common expected error
} else {
throw e; // re-throw the error unchanged
}
}
```
This may mimic the syntax from other languages, like Java:
```java
try {
myRoutine();
} catch (RangeError e) {
// statements to handle this very common expected error
}
// Other errors are implicitly re-thrown
```
### Nested try blocks
First, let's see what happens with this:
```js
try {
try {
throw new Error("oops");
} finally {
console.log("finally");
}
} catch (ex) {
console.error("outer", ex.message);
}
// Logs:
// "finally"
// "outer" "oops"
```
Now, if we already caught the exception in the inner `try` block by adding a `catch` block:
```js
try {
try {
throw new Error("oops");
} catch (ex) {
console.error("inner", ex.message);
} finally {
console.log("finally");
}
} catch (ex) {
console.error("outer", ex.message);
}
// Logs:
// "inner" "oops"
// "finally"
```
And now, let's rethrow the error.
```js
try {
try {
throw new Error("oops");
} catch (ex) {
console.error("inner", ex.message);
throw ex;
} finally {
console.log("finally");
}
} catch (ex) {
console.error("outer", ex.message);
}
// Logs:
// "inner" "oops"
// "finally"
// "outer" "oops"
```
Any given exception will be caught only once by the nearest enclosing `catch` block unless it is rethrown. Of course, any new exceptions raised in the "inner" block (because the code in `catch` block may do something that throws), will be caught by the "outer" block.
### Returning from a finally block
If the `finally` block returns a value, this value becomes the return value of the entire `try-catch-finally` statement, regardless of any `return` statements in the `try` and `catch` blocks. This includes exceptions thrown inside of the `catch` block:
```js
(() => {
try {
try {
throw new Error("oops");
} catch (ex) {
console.error("inner", ex.message);
throw ex;
} finally {
console.log("finally");
return;
}
} catch (ex) {
console.error("outer", ex.message);
}
})();
// Logs:
// "inner" "oops"
// "finally"
```
The outer "oops" is not thrown because of the return in the `finally` block. The same would apply to any value returned from the `catch` block.
## Specifications
{{Specifications}}
## Browser compatibility
{{Compat}}
## See also
- {{jsxref("Error")}}
- {{jsxref("Statements/throw", "throw")}}
|