【JavaScript】制御命令③
ループを途中でスキップ/中断する(break/continue命令)
while/do..while、for、for..in命令は
あらかじめ決められた終了条件を満たしたタイミングで
ループを終了する
それに対して
「特定の条件を満たした場合にループを強制的に中断したい」
というケースもある
この場合にbreak命令を利用する
var result = 0; for(var i = 0; i <= 100; i++) { result += i; if (result > 1000) { break; } } document.writeln('合計値が1000を超えるのは' + i); //合計値が1000を超えるのは45
変数iを1~100の間で加算していき
合計値(変数result)が1000を超えたところでループを脱出する
このようにbreak命令はif命令と
セットで利用するのが一般的である
ループを完全に中断してしまうのではなく
「現在のループだけをスキップして次のループを継続して実行したい」
という場合はcontinue命令を使用する
以下例!
var result = 0; for(var i = 0; i < 100; i++) { if (i % 2 == 0) { continue; } result += i; }
これは変数iを1~100の間で奇数のみ加算し
その合計値を求めるための記述、ほっほー
カウンタ変数iが偶数(変数iが2で割り切れる)の場合のみ
処理をスキップすることで奇数だけの合計値を求めている
なるほど、なるほどー!
- break命令
- ループ全体を完全に脱出する
- continue命令
- 現在の周回をスキップする
はあく!
ネストされたループを一気に脱出する(ラベル構文)
ネストされたループの中でbreak/continue命令を使用した場合
デフォルトでは最も内側のループを脱出/スキップする
for(var i = 1; i < 10; i++) { for(var j = 1; j < 10; j++) { var k = i * j if (k > 30) { break; } document.write(k + ' '); } document.write('<br />'); }
この例では
変数k(カウンタ変数i、jの積)が
30を超えたところでbreak命令を実行する
これによって内側のループを脱出する
最終的に「積が30以下の値のみを表示する九九表」が
生成される
これを
「一度、積が30を超えたら九九表の出力そのものを停止したい」
としたら
脱出先のループの先頭に
ラベルを指定する必要がある
kuku : for(var i = 1; i < 10; i++) { for(var j = 1; j < 10; j++) { var k = i * j if (k > 30) { break kuku; } document.write(k + ' '); } document.write('<br />'); }
例のようにラベルは
ラベル名 :
という形で指定する
ラベル名は任意の識別子を指定できる
ここで再び識別子の命名規則のおさらいを
- 1文字目は英字/アンダースコア(_)/ドル記号($)のどれか
- 2文字目以降は、1文字目で利用可能な文字か数字
- 変数名に含まれる英数字の小文字/大文字は区別される
- JSで意味を持つ予約語じゃないこと
さすがに覚えた
break ラベル名;
break/continue命令側では
上記のような形式でラベルを指定すると
内側のループではなく
ラベルの付いたループを脱出することができる
うむうむ
switchのcaseブロックと同じような書き方だなーとか
例外処理(try..catch..finally命令)
アプリケーションを実行していると
- 数値を受け取ることを想定した関数に文字列が渡された
- 変数を参照しようとしたら未定義であった
などのプログラミング時には
想定しなかったさまざまなエラー(例外)が
発生するものである
例外の種類によってはプログラミング時に
未然に回避できるものもあるが
- 引数に予期せぬ値が渡された
- 関数やクラスを意図せぬ方法で利用された
など、外部要因に依存する処理では
例外の発生を完全に防ぐことはできない
このような場合にも
スクリプト全体が停止しないようにするのが
例外処理の役割である
例外処理を実現するのは
try..catch..finally命令である
以下構文!
try { 例外が発生するかもしれない命令(群) } catch(例外情報を受け取る変数) { 例外が発生した際に実行する命令(群) } [finally { 例外の有無に関わらず、査収的に実行される命令(群) }]
以下具体例
var i = 1; try { i = i * j; //例外発生 } catch(e) { document.writeln(e.message); } finally { document.writeln('処理は完了しました'); }
j is not defined
処理は完了しました
もしtry..catch..finally命令を利用していない場合
例外(未定義の変数を参照しようとしたため)が発生し
スクリプトが停止してしまうはず、ほう‥
しかし、tryブロックで例外が発生した場合には
処理はそのままcatchブロックに引き継がれ
後続のfinallyブロックも
きちんと処理されていることが確認できる
例外情報はcatchブロックに
Errorオブジェクト(例では変数e)として引き渡される
ここではErrorオブジェクトに用意されている
messageプロパティをつかって
エラーメッセージを表示しているだけだが
その他のブロック同様、必要に応じて
任意の処理を記述することができる
例外はプログラム中に発生したものを
補足するばかりではなく
throw命令を利用し
自分で発生させることもできる
以下構文
throw new Error(エラーメッセージ)
var x = 1; var y = 0; try { if(y == 0){ throw new Error('0で除算しようとしました'); } var z = x / y; } catch(e) { document.writeln(e.message); }
0で除算しようとしました
例外を発生させることを「例外をスローする」ともいう
例では
「変数yが0である場合にErrorオブジェクトを生成し
処理をcatchオブジェクトに移す」
ようにしている
うむうむ
throw命令は多くの場合
if命令のような条件分岐命令と一緒に使用される
改めて自覚しておくべきなのが
例外処理が有効になるのは
スクリプトに対して、外から何らかの値が渡される場合
具体的には実際にそういうスクリプトを書くときに学ぶべし
うむうむー制御命令多くてあたま混乱するな
ちょっとまとめよう