「JavaScript/例外処理」の版間の差分

削除された内容 追加された内容
→‎throw: 例外オブジェクトについての説明を追加
83 行
 
==大域脱出==
 
例外は大域脱出に使うこともできます。大域脱出とは、入れ子になった制御構造の内側から外側に制御を戻すことです。<code>break</code>や<code>return</code>は最内側の制御構造(<code>for</code>/<code>while</code>/<code>switch</code>と関数)を抜け出すだけですが、例外を<code>throw</code>すると文や関数を超えて制御が移ります。この性質を利用すると二重以上のループや関数を脱出することができるのです。
 
ですが、大域脱出を使うことは極力避けてください。breakやreturnを[https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/label ラベル]と共に使用することで、ほとんどの場合は帯域脱出を使うことなく要件を達成できます。
JavaScript 1.6で追加された[[JavaScript/Array/prototype/forEach|forEach]]メソッドを使用すると、次のようにして[[JavaScript/Array|配列]]の各要素について処理を行うことができます。
 
<source lang="javascript">
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array.forEach(function(n){
if ( n == 5 ) {
alert(n); // "5" と表示
return; // でも抜けられない
}
});
</source>
 
この例では配列の中から 5 という数字を見つけて表示し、ループを抜けることを期待していますが、returnをしてもforEachメソッドによって呼ばれた無名関数から脱出するだけで、ループそのものは最後の 9 まで回ってしまいます。その分の処理に掛かる時間は無駄になってしまいます。
 
このような場合、try-catch文による例外処理を応用すると反復処理から抜け出すことができます。
 
<source lang="javascript">
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
try {
array.forEach(function(n){
if ( n == 5 ) {
alert(n); // "5" と表示
throw false; // 例外を投げる
}
});
}
catch (e) {
if (e) throw e; // もしfalseでない例外が発生していたら中断
}
 
// 以降の処理
</source>
 
こうすると、配列の中から 5 という値が見つかった時点で例外を発生し、forEachメソッドの反復を抜けるため、処理に掛かる時間を短縮することができます。
 
catch節は単に見せかけの例外を捕捉するだけで、そのまま以降の処理を続けますが、もし本当に意図しない例外がtry節の中で発生していたときのために、<code>throw false;</code>で投げた例外<code>e</code>が<code>false</code>になっていない場合(<code>true</code>の場合)は同じ例外を再度発生させるようにしています。
 
=== 注意 ===
 
<code>some</code>や<code>indexOf</code>など、配列の要素を舐める関数をうまく使うと、例外に頼らずとも効率よく動くコードが書けることがほとんどです。例外をエラー通知以外のことに使うのは裏技的な最後の手段と捉え、極力避けましょう。
 
[[Category:JavaScript|れいかいしより]]