概要
try…catch 構文は試したい文のブロックをマークし、例外を投げる必要がある場合のレスポンスを指定するための構文です。
構文
try {
try_statements
}
[catch (exception_var_1 if condition_1) { // non-standard
catch_statements_1
}]
...
[catch (exception_var_2) {
catch_statements_2
}]
[finally {
finally_statements
}]
try_statements- 実行される文。
catch_statements_1,catch_statements_2- try ブロックの中で例外が投げられた場合に実行される文です。
exception_var_1,exception_var_2- 関連する
catch節に対して例外オブジェクトを保持する識別子。
condition_1- 条件式。
finally_statementstry文が完了した後に実行される文。これらの文は、例外が投げられたり捕捉されたかどうかに関係なく実行されます。
説明
try 文は、1 つ以上の文を含む try ブロック、および少なくとも 1 つの catch 節、または finally 節、もしくはその両方から成り立っています。すなわち、try 文には 3 つの形式があります:
try...catchtry...finallytry...catch...finally
catch 節は、例外が try ブロックの中で投げられたのなら何をすべきか指定する文を含みます。すなわち、try ブロックは成功すべきで、それが成功しなかったのなら、制御は catch ブロックに渡るべきです。try ブロック内 (または try ブロック内から呼び出された関数の中) の任意の文が例外を投げたのなら、制御は即座に catch 節へ移ります。例外が try ブロックの中で投げられなかったのなら、catch 節は飛ばされます。
finally 節は、try ブロックおよび (1 つまたは複数の) catch 節が実行された後、なおかつ try 文の次の文の前に実行されます。これは、例外が投げられた、または捕捉されたかどうかに関係なく、常に実行されます。
1 つ以上の try 文をネストすることもできます。内側の try 文が catch 節を持たないのなら、囲んでいる try 文の catch 節に入ります。
Java の例外を操作するためにも try 文を使います。Java の例外に関する情報は Core JavaScript 1.5 ガイドを参照してください。
無条件 catch 節
単独の無条件 catch 節が使われたときは、任意の例外が投げられると catch 節に入ります。たとえば、次のコードの中で例外が生じたとき、制御は catch 節に移動します。
try {
throw "myException"; // 例外を生成します
}
catch (e) {
// 任意の例外を操作するための文
logMyErrors(e); // エラーハンドラに例外オブジェクトを渡します
}
条件付き catch 節
非標準
この機能は標準ではなく、標準化の予定もありません。公開されている Web サイトには使用しないでください。ユーザーによっては使用できないことがあります。実装ごとに大きな差があることもあり、将来は振る舞いが変わるかもしれません。
特定の例外を操作するために、1 つ以上の条件付き catch 節を使うこともできます。この場合、特定の例外が投げられると、適切な catch 節に入ります。次の例では、try ブロックの中のコードは 3 つの例外: TypeError、RangeError、および EvalError、を投げる可能性があります。例外が生じたとき、制御は適切な catch 節に移動します。例外が、指定された例外のどれでもなく、かつ無条件 catch 節が見つかったのなら、制御はその catch 節に移動します。
1 つ以上の条件付き catch 節とともに無条件 catch 節を使うのなら、無条件 catch 節は最後に指定されなくてはいけません。そうでなければ、無条件 catch 節が全種類の例外を、それらが条件付きのものに到達する前に、途中で捕捉します。
注: この機能は ECMAScript 仕様の一部ではありません。
try {
myroutine(); // 3 つの例外を投げる可能性があります
} catch (e if e instanceof TypeError) {
// TypeError 例外を操作するための文
} catch (e if e instanceof RangeError) {
// RangeError 例外を操作するための文
} catch (e if e instanceof EvalError) {
// EvalError 例外を操作するための文
} catch (e) {
// 任意の指定されていない例外を操作するための文
logMyErrors(e); // エラーハンドラに例外オブジェクトを渡します
}
続いて、"条件付きcatch節"と同じことをECMAScript仕様に準拠したJavaScriptを使って実装する方法も示します(これは明らかに冗長ですが、かわりにどの環境でも動作します):
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
}
}
例外識別子
例外が try ブロックの中で投げられたときは、exception_var (たとえば、catch (e) における e) が throw 文により指定された値を保持します。投げられた例外についての情報を得るために、この識別子を使うことができます。
この識別子は catch 節にローカルです。すなわち、これは catch 節に入ったときに作成され、catch 節が実行を終了した後では、この識別子はもはや利用できません。
finally 節
finally 節は、try ブロックおよび (1 つまたは複数の) catch 節が実行された後、なおかつ try 文の次の文の前に実行される文を含みます。finally 節は、例外が投げられたかどうかに関係なく実行されます。例外が投げられたのなら、たとえ例外を操作する catch 節がなかったとしても、finally 節の中の文は実行されます。
例外が生じたときに、スクリプトを潔く失敗させるために finally 節を使うことができます。たとえば、スクリプトが結び付けていたリソースを解放する必要があるかもしれません。次の例ではファイルを開き、そのファイルを使う文を実行します (サーバーサイド JavaScript ではファイルにアクセスできます)。ファイルが開かれている間に例外が投げられたのなら、スクリプトが失敗する前に finally 節はファイルを閉じます。
openMyFile()
try {
// リソースを結び付けます
writeMyFile(theData);
}
finally {
closeMyFile(); // リソースを常に閉じます
}
Examples
入れ子になったtryブロック
最初に、これで何が起きるか見てみましょう:
try {
try {
throw new Error("oops");
}
finally {
console.log("finally");
}
}
catch (ex) {
console.error("outer", ex.message);
}
// Output:
// "finally"
// "outer" "oops"
続いて、catch ブロックを追加して内部の try ブロックで例外をキャッチしてみます。
try {
try {
throw new Error("oops");
}
catch (ex) {
console.error("inner", ex.message);
}
finally {
console.log("finally");
}
}
catch (ex) {
console.error("outer", ex.message);
}
// Output:
// "inner" "oops"
// "finally"
そして、エラーを再スローします。
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);
}
// Output:
// "inner" "oops"
// "finally"
// "outer" "oops"
再スローされない限り任意の例外は、最も内側のキャッチブロックで一度だけ捕捉されます。もちろん、何らかの例外が "内部" のブロックで発生した場合(catch ブロックのコードで何らかのスローが発生した場合)、"外部" のブロックでキャッチされます。
finally ブロックからの return
finally ブロックが値を返した場合、try ブロックと catch ブロックの return ステートメントにかからわず、この値が try-catch-finally 全体の戻り値になります。これは catch ブロック内でスローされた例外も含みます:
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);
}
// Output:
// "inner" "oops"
// "finally"
外部の "oops" は finally ブロックで return されているため、スローされません。 同じことが、 catch ブロックから返されているそのほかの値にも適用されます。
仕様
| 仕様 | ステータス | コメント |
|---|---|---|
| ECMAScript 3rd Edition (ECMA-262) | 標準 | 初期定義。JavaScript 1.4 で実装されました。 |
| ECMAScript 5.1 (ECMA-262) try statement の定義 |
標準 | |
| ECMAScript 2015 (6th Edition, ECMA-262) try statement の定義 |
標準 | |
| ECMAScript 2017 Draft (ECMA-262) try statement の定義 |
ドラフト | 現在の ECMA-262 標準には含まれていません。複数の catch 節と条件付き catch 節(SpiderMonkey 拡張、JavaScript 1.5)。 |
ブラウザ実装状況
| 機能 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| 基本サポート | (有) | (有) | (有) | (有) | (有) |
| 条件付き catch (非標準) |
未サポート | (有) | 未サポート | 未サポート | 未サポート |
| 機能 | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
|---|---|---|---|---|---|---|
| 基本サポート | (有) | (有) | (有) | (有) | (有) | (有) |
| 条件付き catch (非標準) |
未サポート | 未サポート | (有) | 未サポート | 未サポート | 未サポート |