try...catch 文
try...catch
文はテストしたい文のブロックを指定し、さらに投げられるであろう例外に対する 1 つ以上の対処方法を指定します。例外が投げられると try...catch
文がそれを受け取ります。
try...catch
文は 1 つの try
ブロックと 0 個以上の catch
ブロックからなります。前者は 1 つ以上の文からなります。後者は try ブロックで例外が投げられた場合にどうするかを指定する文からなります。すなわち、成功させたい try
ブロックと、失敗した場合にコントロールを渡す catch
ブロックからなります。try
ブロック内(もしくは try
ブロック内から呼び出された関数内)のいずれかの文が例外を投げた場合、コントロールはすぐに catch
ブロックに移ります。try
ブロックで例外が投げられなかった場合は catch
ブロックは飛ばされます。finally
ブロックは try
および catch
ブロックが実行された後に実行されます。ただし try...catch
文の後に続く文より先に実行されます。
次の例では try...catch
文を使用しています。この例では渡された値に基づいて配列から月の名前を取り出す関数を呼び出します。値に対応する月の数字 (1-12) がなかったら、InvalidMonthNo
という値を持つ例外が投げられ、catch
ブロックの中の文は monthName
という変数に unknown
という値をセットします。
function getMonthName (mo) { mo=mo-1; // 月の数字を配列のインデックスに合わせる (1=Jan, 12=Dec) var months=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul", "Aug","Sep","Oct","Nov","Dec"); if (months[mo] != null) { return months[mo] } else { throw "InvalidMonthNo" } } try { // テストする文 monthName=getMonthName(myMonth) // 関数は例外を投げることがある } catch (e) { monthName="unknown" logMyErrors(e) // 例外オブジェクトをエラー処理部分に渡す }
catch ブロック
単一の catch
ブロックを使用すると、try
ブロックで生じうるすべての例外を扱うことができます。また、扱う例外の種類によって catch
ブロックをそれぞれに分けることもできます。
単一の catch ブロック
try
ブロックで投げられるいかなる例外にも対応したエラー処理コードを実行するには、try...catch
文で catch
を 1 つ使用してください。
単一の catch
ブロックは次のように使用します。
catch (catchID) { statements }
catch
ブロックは、throw
文で指定された値を持つ識別子(上記の構文における catchID
)を指定します。この識別子を使用することで投げられた例外についての情報を得ることができます。JavaScript は catch
ブロックに入るときにこの識別子を作成します。識別子は catch
ブロックにいる間だけ持続します。つまり、catch
ブロックの実行が終了するとその識別子はもう使えなくなります。
例えば、次のコードは例外を投げます。例外が生じるとコントロールが catch
ブロックに移ります。
try { throw "myException" // 例外を生成 } catch (e) { // どんな例外も扱う文 logMyErrors(e) // 例外オブジェクトをエラー処理部分に渡す }
複数の catch ブロック
1 つの try
文に対して、複数の条件についての catch
ブロックを使うことができます。そして、そのそれぞれがそれぞれの種類の例外を担当します。この場合、そのブロックで指定されている例外が投げられたときだけ、適切な条件の catch
ブロックに入ることになります。すべての未指定の例外のために、すべての例外に対応した catch
ブロックをその文の最後の catch ブロックとしてオプション的に設けることもできます。
例えば、次の関数は 3 つの別の関数(どこかで定義済み)を呼び出します。この関数はその引数が妥当であるかを確かめます。妥当性確認関数が確認対象の構成要素が妥当でないと決定した場合、その関数は 0 を返し、該当する例外を呼び出し元に投げさせます。
function getCustInfo(name, id, email) { var n, i, e; if (!validate_name(name)) throw "InvalidNameException" else n = name; if (!validate_id(id)) throw "InvalidIdException" else i = id; if (!validate_email(email)) throw "InvalidEmailException" else e = email; cust = (n + " " + i + " " + e); return (cust); }
おのおのの条件の catch
ブロックは適当な例外処理部分にコントロールを渡します。
try { // 関数は 3 つの例外を投げうる getCustInfo("Lee", 1234, "[email protected]") } catch (e if e == "InvalidNameException") { // 不正な名前に対しての処理部分を呼び出す bad_name_handler(e) } catch (e if e == "InvalidIdException") { // 不正な ID に対しての処理部分を呼び出す bad_id_handler(e) } catch (e if e == "InvalidEmailException") { // 不正なメールアドレスに対しての処理部分を呼び出す bad_email_handler(e) } catch (e){ // 何が起きるかはわからないが、そのログをとる logError(e) }
finally ブロック
finally
ブロックは、try および catch ブロックの実行が終わった後に実行される文からなります。ただし try...catch
文の後に続く文より前に実行されます。finally
ブロックは例外が投げられても投げられなくても実行されます。例外が投げられた場合、finally
ブロック内の文はたとえ例外処理をする catch ブロックがなくても実行されます。
finally
ブロックを使用することで、例外発生時に適切にスクリプトを停止させることができます。例えば、スクリプトで使用していたリソースを解放する必要があるかもしれません。次の例ではファイルを開き、そのファイルを使用する文を実行します(サーバサイド JavaScript ではファイルにアクセスできます)。ファイルを開いている間に例外が投げられると、スクリプトが停止する前に finally
ブロックがそのファイルを閉じます。
openMyFile(); try { writeMyFile(theData); // エラーを投げる可能性がある }catch(e){ handleError(e); // エラーを受け取り、それを処理する }finally { closeMyFile(); // 常にリソースを閉じる }
try...catch 文のネスト
1 つ以上の try...catch
文を入れ子にすることができます。内側の try...catch
文に catch ブロックがない場合、囲んでいる try...catch
文の catch ブロックがマッチしているか確認されます。