try...catch

try...catch 文は、試す文のブロックをマークし、例外が発生したときの応答を指定します。

試してみましょう

構文

try {
  try_statements
}
catch (exception_var) {
  catch_statements
}
finally {
  finally_statements
}
try_statements

実行される文です。

catch_statements

try ブロックの中で例外が発生した場合に実行される文です。

exception_var

関連する catch 節に対して例外オブジェクトを保持する識別子です。

finally_statements

try 文が完了した後に実行される文です。これらの文は、例外が発生されたり捕捉されたりしたかどうかに関係なく実行されます。

解説

try 文は、1 つ以上の文を含む try ブロックにより構成されます。文が 1 つであっても、常に {} を使用する必要があります。1 つ以上の catch ブロック、または finally ブロックが存在する必要があります。すなわち、try 文には 3 つの形態があります。

  • try...catch
  • try...finally
  • try...catch...finally

catch ブロックは、例外が try ブロックの中で発生した場合に何をするかを指定する文を含みます。try ブロック内 (または try ブロック内から呼び出された関数の中) のいずれかの文で例外が発生した場合は、制御は即座に catch ブロックへ移ります。try ブロックの中で例外が発生しなかった場合は、catch ブロックは飛ばされます。

finally ブロックは、try ブロックおよび catch ブロックの実行が完了した後で実行されます。これは常に実行され、例外が発生したかどうか、捕捉されたかどうかには関係ありません。

1 つ以上の try 文を入れ子にする事ができます。内側の try 文が catch ブロックを持っていない場合、それを囲んでいる try 文の catch ブロックに入ります。

try を使用して JavaScript の例外を処理することもできます。 JavaScript の例外に関する情報は JavaScript ガイドを参照してください。

無条件の catch ブロック

catch ブロックが使われている場合、try ブロックの中から任意の例外が発生すると、catch ブロックが実行されます。例えば、以下のコードで例外が発生すると、制御は catch ブロックへ移動します。

try {
  throw 'myException'; // 例外を生成
} catch (e) {
  // 任意の例外を操作するための文
  logMyErrors(e); // エラーハンドラーに例外オブジェクトを渡します
}

catch ブロックは例外の値を保持する識別子 (上記の例では e) を指定します。この値は catch ブロックのスコープ内でのみ利用できます。

条件付き catch ブロック

「条件付き catch ブロック」は、下記のように try...catch ブロックを if...else if...else 構造と組み合わせることで作成することができます。

try {
  myroutine(); // 3 つの例外が発生する可能性があります
} catch (e) {
  if (e instanceof TypeError) {
    // TypeError 例外を処理するための文
  } else if (e instanceof RangeError) {
    // RangeError 例外を処理するための文
  } else if (e instanceof EvalError) {
    // EvalError 例外を処理するための文
  } else {
    // 任意の指定されていない例外を操作するための文
    logMyErrors(e); // エラーハンドラーに例外オブジェクトを渡す
  }
}

よくある使用例としては、次のように想定済みの一部のエラーのみを捕捉 (および無視) し、それ以外の場合はエラーを送出し直す場合です。

try {
  myRoutine();
} catch (e) {
  if (e instanceof RangeError) {
    // 頻発する想定済みのエラーを処理する文
  } else {
    throw e;  // エラーを変更しないまま送出し直す
  }
}

例外識別子

例外が try ブロックの中で発生したときは、exception_var (たとえば、catch (e) における e) が例外の値を保持します。この識別子を使用して、発生した例外についての情報を取得することができます。この識別子は catch ブロックのスコープでのみ利用できます。例外の値が必要ない場合にはこれは省略できます。

function isValidJSON(text) {
  try {
    JSON.parse(text);
    return true;
  } catch {
    return false;
  }
}

finally ブロック

finally ブロックには、try ブロックおよび catch ブロックを実行した後で、try...catch...finally の次の文が実行される前に実行される文が入ります。なお、finally ブロックは例外が発生するかどうかにかかわらず実行されます。また、例外が発生した場合、finally ブロックは例外を処理する catch ブロックがなくても実行されます。

次の例では finally ブロックの一つの使用例を示します。このコードはファイルを開き、それからファイルを使用する分を実行します。finally ブロックは、例外が発生したとしてもその後で確実にファイルを閉じるよう保証します。

openMyFile();
try {
  // リソースを結び付けます
  writeMyFile(theData);
} finally {
  closeMyFile(); // リソースを常に閉じます
}

入れ子になった try ブロック

最初に、次のもので何が起きるか見てみましょう。

try {
  try {
    throw new Error('oops');
  } finally {
    console.log('finally');
  }
} catch (ex) {
  console.error('outer', ex.message);
}

// Output:
// "finally"
// "outer" "oops"

ここで、既に内部の try ブロックに catch ブロックを追加しているので、既に例外を捕捉しています。

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 ブロックで一度だけ捕捉されます。もちろん、何らかの例外が「内側の」のブロックで発生した場合 (catch ブロックのコードで例外が発生することを行った場合)、「外側の」ブロックで捕捉されます。

finally ブロックからの return

finally ブロックが値を返す場合、その値が try-catch-finally 全体の返値になり、 try ブロックや catch ブロックの return 文に関係なくなります。 これは catch ブロック内で例外が発生した場合も含まれます。

(function() {
  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);
  }
})();

// 出力結果:
// "inner" "oops"
// "finally"

外側の "oops" は finally ブロックに return があるため送出されません。同じことが、catch ブロックから返されているそのほかの値にも適用されます。

仕様書

Specification
ECMAScript Language Specification
# sec-try-statement

ブラウザーの互換性

BCD tables only load in the browser

関連情報