Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

  1. トップページ
  2. JavaScript応用編 - ブロックとラベルについて

ブロックとラベルについて

みなさまどうも。続きまして『ブロック』と『ラベル』について色々と解説していきたいと思います。

まずは『ブロック』からいきます。これは解説がいらないレベルなのかもしれませんが、『ラベル』の解説の時に必要なので一応解説しておきます。

『ブロック』は『ブロック文』、『複合文』、または『コードブロック』と呼ばれ、複数の文をグループ化するときに使われる構文です。というわけでサンプルです。

for(var i = 0; i < 10; ++i){

}

はい、ただの『for文』ですね。そのただの『for文』の右側あたりに注目です。『{}』がありますね。実はこれに名前がついていて、これが『ブロック』と呼ばれる部分になります。これまで沢山書いてきましたよね。

ちょっとした注意点ですが、JavaScriptでは『ブロック』の中と外でスコープが切り替わったりしません。C言語とかでは『ブロック』の中と外でスコープが切り替わる仕様なのですが、JavaScriptでのスコープはグローバルスコープと関数スコープしか存在しませんので間違えないように気をつけてくださいね。特に他言語に精通している方は要注意です。あと『ブロック』には末尾の『;』は書かなくてOKです。こちらも覚えておきましょう。

というわけで『ブロック』の説明は以上です。続いて『ラベル』についてやっていきましょう。JavaScriptには『ラベル』という機能があり、文とか『ブロック』とかに名前を付けることができます。サンプルはこちらです。

test: console.log("ラベルだよぉ...");

このサンプルは『test』という名前のラベルを付けてます。このように識別子(名前)を記述して、その後ろに『:』を付けてその右に処理を書きます。識別子に使用可能な文字列は変数などと同じです。

※ JavaScriptの識別子の命名ルールについてはこちらへ。

複数行の処理を書きたい場合は『ブロック』(『{}』)で包んであげればOKです。

test: {
    console.log("ラベルだよぉ...");
    console.log("ラベルだってばぁ...");
    console.log("もう何回言わせるのぉ...");
    console.log("エッチ...");
}

さらにループ処理にラベルを付けることができます。

test: for(var i = 0; i < 10; ++i){
    console.log("ラベルだよぉ...");
    console.log("ラベルだってばぁ...");
    console.log("もう何回言わせるのぉ...");
    console.log("エッチ...");
}

『if文』とかでもOKです。

test: if(true){
    console.log("ラベルだよぉ...");
    console.log("ラベルだってばぁ...");
    console.log("もう何回言わせるのぉ...");
    console.log("エッチ...");
}

ここまではOKそうでしょうか。さて、この『ラベル』という機能、名前が付けられるのは分かったもののあんまり意味がなさそうですね。実際上記のサンプルとかだと『ラベル』を付けている意味が全くありません。

というわけで前回の記事で紹介した『continue文』、または『break文』を組み合わせてみましょう。以下は『ラベル』と『continue文』を組み合わせたサンプルです。

var i = 0;
loop: while(i < 5){
    ++i;
    if(i < 2) continue loop;
    console.log(i);
}

上記のサンプルを実行させるとこうなります。

2
3
4
5

数値『1』が飛ばされて数値『2』から出力されていますね。このように『continue』と記述したあとに半角スペースとかを空けてラベル名を記述することでその『ラベル』の位置までジャンプしたりすることができます。

『break』も同じ記法でOKです。

var j = 0;
loop: while(j < 5){
    ++j;
    if(j >= 2) break loop;
    console.log(j);
}

これを実行するとこうなります。

1

数値『1』が出力された時点で処理が止まっていますね。『continue文』、または『break文』と『ラベル』を組み合わせるとこんな感じの処理が実装できます。

しかし、お察しの良い方は不思議に思ったと思います。さっきのサンプルは以下のように『ラベル』を使用しなくても実装できてしまいますよね。それは大正解でございます。

var i = 0; // さっきのサンプルと同じ結果になります。
loop: while(i < 5){
    ++i;
    if(i < 2) continue;
    console.log(i);
}
var j = 0; // さっきのサンプルと同じ結果になります。
loop: while(j < 5){
    ++j;
    if(j >= 2) break;
    console.log(j);
}

どうやらまだ『ラベル』を使用する意味がないようです。

じゃあどんな時に『ラベル』を使うのかというと『ブロック』の外側にある処理を『continue』、または『break』したい時に使用します。以下のサンプルをみてみましょう。

for(var i = 0; i < 10; ++i){
    for(var j = 0; j < 10; ++j){ // 『break文』でここの処理が停止します。
        break;
    }
}
console.log(i); // 『10』と出力されます。

上記のサンプルは『for文』の中に『for文』がいて、その中で『break』が記述してあるという感じですね。『break』の対象となるのは『for文』の中の『for文』になります。

この状態で一番内側の『for文』から外側の『for文』を停止したい、となった場合は『ラベル』を使用することでその処理が実装できるようになります。

loop: for(var i = 0; i < 10; ++i){ // 『break文』でここの処理が停止します。
    for(var j = 0; j < 10; ++j){
        break loop;
    }
}
console.log(i); // 『0』と出力されます。

『ラベル』はこんな感じで使用します。『continue文』でも同じような記述で実装できるので暇があったら試してみてください。

あと『continue文』はループ処理の中でしか使えないという制約があるので使用できませんが、『break文』ならばループ処理などでなくても『ラベル』を指定することでその処理を停止することができます。

test: {
    break test;
    console.log(true); // ここは実行されません。
}

ちなみに『ラベル』を指定しないとダメです。文法エラーになっちゃいます。

test: {
    break; // 『ラベル』の指定がないのでエラーです。
    console.log(true);
}

こんな感じですね。

あと『ラベル』の識別子についての補足です。

『ラベル』は同じ『ラベル』の中だと同じ識別子は付けられません。

test: {
    test:{ // 『test』という識別子は外側で使用されているためエラーです。

    }
}

しかし、入れ子関係になっていない場合は同じ識別子を使用できます。

test: {

}

test:{ // これはOKです。

}

上記の場合もちゃんと別の『ラベル』だと扱ってくれているので、『continue文』や『break文』を記述したときの対象は、自身が属している『ラベル』となります。

test: {
    break test;
    console.log(0); // 実行されません。
}

test:{
    console.log(1); // 実行されます。
}

そして『ラベル』に使用される識別子は変数や関数とは違う『名前空間』となっています。なので以下のように変数と『ラベル』で同じ識別子を使用しても名前衝突は起こりません。

var x = 0;

x: { // 変数とは違う『名前空間』なので変数の上書きはされません。
}

console.log(x); // 『0』と出力されます。

『ラベル』の識別子についての補足は以上となりますね。

尚、JavaScriptで『ラベル』を使用する構文は『continue文』と『break文』のみになりますのでこちらも覚えておきましょう。

『名前空間』(なまえくうかん)とは英語で『Namespace』(ネームスペース)と呼ばれ、名前の集合を分別するための概念の事を指します。

どういうことかというと、例えば今ここにスズキタロウ君とサトウタロウ君がいたとして、「タロウくーん!」と呼ぶと恐らく2人が振り向いちゃいます。

どっちか片一方を呼びたい場合は苗字をつけて呼びますよね。この苗字に当たるのが『名前空間』という概念になります。ようするにカテゴリー分けです。

JavaScriptで『名前空間』を利用するとすると以下のような感じですね。

var PC = {}, SP = {}; // PC用とスマホ用にオブジェクトを生成しておきます。

SP.scrollBanner = function(){ // スマホでしか使用しない処理はグローバルオブジェクト『SP』の中で定義します。
    // ここに処理。
};

上記のようにすることで間違えて同じ名前(識別子)で定義しちゃって上書きしてしまう問題、つまり『名前衝突』を引き起こす可能性がぐっと減り、さらにオブジェクトを切り替えれば同じ名前が使用できるため、名前を考える時間を少なくすることができます。

よく使用されるテクニックなので覚えておきましょう。

JavaScript以外の言語では『名前空間』を自作できる構文が用意されていたりすることが多いのですが、JavaScriptでは存在しませんので『名前空間』の実装方法は様々な形があります。もしご興味あれば調べてみてください。

最後になりますが、実は今回解説した『ラベル』は好んで使われる構文ではありません。この『ラベル』という機能は『goto文』と近い動作となっているため、なるべく使用しないほうが無難、という風潮になっています。著者もほぼ使いません。

ただ、『ラベル』の記法を知らないと『ラベル』が使用されているソースコードが読めなくなってしまうかもしれないので、記法だけは覚えておくようにしておくと良いかもしれません。

『goto文』とは特定の場所へ移動(ジャンプ)できる構文です。JavaScriptには実装されていませんが、C言語では以下のような感じで『goto文』が記述できます。

loop:
    // この辺に処理。

goto loop; // 『loop』のところへジャンプします。

この『goto文』は沢山使用されるとプログラムを読み進める際に色々な場所へジャンプしなくてはならなくなり、可読性が非常に下がってしまう事が多いため今現在では「なるべく使わないようにしましょう」という風潮になっています。

まあ個人的にはちょっとしたジャンプが有効な場面でなるならば使ってしまっても全然構わないと思っていますが、禁じ手だと考えている方も結構多いので使用する際の用法用量にはご注意下さい。

というわけで以上です。長くなってすみません、お疲れ様でございました。次の記事では例外処理をやっていきましょう。ではこの辺で失礼致します。またお会いしましょう。

この記事は桜舞が執筆致しました。

著者が愛する小型哺乳類

桜舞 春人 Sakurama Haruto

ISDN時代から様々なコンテンツを制作しているちょっと髪の毛が心配な東京在住のプログラマー。生粋のロングスリーパーで、10時間以上睡眠を取らないと基本的に体調が悪い。好きなだけ寝れる生活を送るのが夢。ゲームとスポーツと音楽が大好き。誰か髪の毛を分けて下さい。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。