みこむらめもむらむらむら

なんかHTML5とかJS勉強とかやりながらめもを綴るブログ

【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 + '&nbsp;');
  }
  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 + '&nbsp;');
  }
  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命令のような条件分岐命令と一緒に使用される

改めて自覚しておくべきなのが
例外処理が有効になるのは
スクリプトに対して、外から何らかの値が渡される場合
具体的には実際にそういうスクリプトを書くときに学ぶべし





うむうむー制御命令多くてあたま混乱するな
ちょっとまとめよう