「JavaScript/制御構造」の版間の差分

出典: フリー教科書『ウィキブックス(Wikibooks)』
削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
{{コラム|0以外にもfailyが}}
M fix lint error (use script)
9 行 9 行
と表示します。
と表示します。


<source lang="javascript">
<syntaxhighlight lang="javascript">
let n = 0;
let n = 0;


21 行 21 行
console.log("0");
console.log("0");
}
}
</syntaxhighlight>
</source>


この様な、分岐を始めとする制御構造はプログラミングを行う上で欠かせません。
この様な、分岐を始めとする制御構造はプログラミングを行う上で欠かせません。
32 行 32 行
次のプログラムは、''n'' < 0(''n''が0より小さい)という条件が真であるときのみ「負の数」と表示します。
次のプログラムは、''n'' < 0(''n''が0より小さい)という条件が真であるときのみ「負の数」と表示します。


<source lang="javascript">
<syntaxhighlight lang="javascript">
let n = -1;
let n = -1;


38 行 38 行
console.log("負の数");
console.log("負の数");
}
}
</syntaxhighlight>
</source>


if文のあとに'''else節'''(エルスせつ、''else clause'')を置くと、else節の文はif文の条件が [[JavaScript/falsy|falsy]] であるときのみ実行されます。
if文のあとに'''else節'''(エルスせつ、''else clause'')を置くと、else節の文はif文の条件が [[JavaScript/falsy|falsy]] であるときのみ実行されます。
次のプログラムは、''n'' < 0(''n''が0より小さい)という条件が真であれば「負の数」、さもなくば(''n''が0以上あるいはNaN(略 ならば)「自然数」と表示します<ref>計算機科学では一般に0を自然数に含め、曖昧さを避けたいときは非負整数とも言います</ref>。
次のプログラムは、''n'' < 0(''n''が0より小さい)という条件が真であれば「負の数」、さもなくば(''n''が0以上あるいはNaN(略 ならば)「自然数」と表示します<ref>計算機科学では一般に0を自然数に含め、曖昧さを避けたいときは非負整数とも言います</ref>。


<source lang="javascript">
<syntaxhighlight lang="javascript">
let n = 0;
let n = 0;


52 行 52 行
console.log("自然数");
console.log("自然数");
}
}
</syntaxhighlight>
</source>


if文とelse節をあわせてif/else文と呼びます。else節は必ず直前のif文に対応するので、if文とelse節の間に余計な文を入れることはできません。
if文とelse節をあわせてif/else文と呼びます。else節は必ず直前のif文に対応するので、if文とelse節の間に余計な文を入れることはできません。
if/else文は次のように何個もつらねることができます。
if/else文は次のように何個もつらねることができます。


<source lang="javascript">
<syntaxhighlight lang="javascript">
let n = 0;
let n = 0;


69 行 69 行
console.log("0");
console.log("0");
}
}
</syntaxhighlight>
</source>


このプログラムは''n'' < 0ならば「負の数」、そうでなく''n'' > 0ならば「正の数」、そうでもないならば「0」と表示します。
このプログラムは''n'' < 0ならば「負の数」、そうでなく''n'' > 0ならば「正の数」、そうでもないならば「0」と表示します。
77 行 77 行
単文(1つの文)しか入っていない場合は、次のように書いても同じことです。
単文(1つの文)しか入っていない場合は、次のように書いても同じことです。


<source lang="javascript">
<syntaxhighlight lang="javascript">
let n = 0;
let n = 0;


86 行 86 行
else
else
console.log("0");
console.log("0");
</syntaxhighlight>
</source>


なお、この場合は条件演算子を用いて簡潔に書けます。
なお、この場合は条件演算子を用いて簡潔に書けます。


<source lang="javascript">
<syntaxhighlight lang="javascript">
let n = 0;
let n = 0;


96 行 96 行
: n > 0 ? "正の数"
: n > 0 ? "正の数"
: "0");
: "0");
</syntaxhighlight>
</source>


if文の条件式はすべてtrueかfalseの[[JavaScript/Boolean|真偽値]]として評価されます。たとえば、数値の0は真偽値に変換するとfalseになるので<ref>falsy</ref>、次のif文のブロックは絶対に実行されません([[w:到達不能コード|デッドコード]])。
if文の条件式はすべてtrueかfalseの[[JavaScript/Boolean|真偽値]]として評価されます。たとえば、数値の0は真偽値に変換するとfalseになるので<ref>falsy</ref>、次のif文のブロックは絶対に実行されません([[w:到達不能コード|デッドコード]])。


<source lang="javascript">
<syntaxhighlight lang="javascript">
if (0) {
if (0) {
// たどりつけない
// たどりつけない
}
}
</syntaxhighlight>
</source>


{{コラム|0以外にもfailyが|他の言語(例えばC言語)では、''n''が0に等しいかどうかは
{{コラム|0以外にもfailyが|他の言語(例えばC言語)では、''n''が0に等しいかどうかは
<source lang="c">if (n == 0) { /* ... */ } </source>
<syntaxhighlight lang="c">if (n == 0) { /* ... */ } </syntaxhighlight>
のほかに
のほかに
<source lang="c">if (!n) { /* ... */ }</source>
<syntaxhighlight lang="c">if (!n) { /* ... */ }</syntaxhighlight>
と書けます、同様に ''n''が0に等しくないかどうかは
と書けます、同様に ''n''が0に等しくないかどうかは
<source lang="c">if (n != 0) { /* ... */ }</source>
<syntaxhighlight lang="c">if (n != 0) { /* ... */ }</syntaxhighlight>
のほかに <source lang="c">if (n) { /* ... */ }</source>
のほかに <syntaxhighlight lang="c">if (n) { /* ... */ }</syntaxhighlight>
とも書けます。
とも書けます。


125 行 125 行
if/else文を用いる場合は、
if/else文を用いる場合は、


<source lang="javascript">
<syntaxhighlight lang="javascript">
if (n % 2 == 0) {
if (n % 2 == 0) {
console.log("偶数");
console.log("偶数");
132 行 132 行
console.log("奇数");
console.log("奇数");
}
}
</syntaxhighlight>
</source>


または
または


<source lang="javascript">
<syntaxhighlight lang="javascript">
if (n % 2) {
if (n % 2) {
console.log("奇数");
console.log("奇数");
143 行 143 行
console.log("偶数");
console.log("偶数");
}
}
</syntaxhighlight>
</source>


条件演算子を用いる場合は、
条件演算子を用いる場合は、


<source lang="javascript">
<syntaxhighlight lang="javascript">
console.log(n % 2 == 0 ? "偶数"
console.log(n % 2 == 0 ? "偶数"
: "奇数");
: "奇数");
</syntaxhighlight>
</source>


または
または


<source lang="javascript">
<syntaxhighlight lang="javascript">
console.log(n % 2 ? "奇数"
console.log(n % 2 ? "奇数"
: "偶数");
: "偶数");
</syntaxhighlight>
</source>


または
または


<source lang="javascript">
<syntaxhighlight lang="javascript">
console.log((n % 2 ? "奇"
console.log((n % 2 ? "奇"
: "偶") + "数");
: "偶") + "数");
</syntaxhighlight>
</source>
または
または


<source lang="javascript">
<syntaxhighlight lang="javascript">
console.log("偶奇"[n % 2] + "数");
console.log("偶奇"[n % 2] + "数");
</syntaxhighlight>
</source>
など。
など。


=== if-else 文の構文===
=== if-else 文の構文===
<source lang="javascript">
<syntaxhighlight lang="javascript">
if (条件式)
if (条件式)
文1
文1
[else
[else
文2]
文2]
</syntaxhighlight>
</source>
{{code|[}}から{{code|]}}までは省略可能を意味し、この場合は「else節は省略可能」を意味します。
{{code|[}}から{{code|]}}までは省略可能を意味し、この場合は「else節は省略可能」を意味します。


184 行 184 行
'''[[w:switch文|switch文]]'''(スイッチぶん、''switch statement'')は、if/else文を何個もつらねて書くことが冗長な場合に用いられます。
'''[[w:switch文|switch文]]'''(スイッチぶん、''switch statement'')は、if/else文を何個もつらねて書くことが冗長な場合に用いられます。


<source lang="javascript">
<syntaxhighlight lang="javascript">
if (keyCode == 37) {
if (keyCode == 37) {
console.log("←");
console.log("←");
200 行 200 行
console.log("?");
console.log("?");
}
}
</syntaxhighlight>
</source>


これはswitch文を使って次のように書くことができます。
これはswitch文を使って次のように書くことができます。
<source lang="javascript">
<syntaxhighlight lang="javascript">
switch (keyCode) {
switch (keyCode) {
case 37:
case 37:
219 行 219 行
default:
default:
console.log("?");
console.log("?");
}</source>
}</syntaxhighlight>


必ずcase節の最後にbreak文を書くのを忘れないでください。
必ずcase節の最後にbreak文を書くのを忘れないでください。
225 行 225 行
switch文はここぞというときに使ってください<ref>JavaScriptのswitch文は、動的なのに静的なC言語の構文を倣ったので'''コラム:switch文の限界と限界突破'''の様なハックを使わない限り恩恵を受けられません。</ref>。
switch文はここぞというときに使ってください<ref>JavaScriptのswitch文は、動的なのに静的なC言語の構文を倣ったので'''コラム:switch文の限界と限界突破'''の様なハックを使わない限り恩恵を受けられません。</ref>。


<source lang="javascript">
<syntaxhighlight lang="javascript">
console.log({ 37: "←", 38: "↑", 39: "→", 40: "↓" }[keyCode] || "?");
console.log({ 37: "←", 38: "↑", 39: "→", 40: "↓" }[keyCode] || "?");
</syntaxhighlight>
</source>


=== switch 文の構文===
=== switch 文の構文===
<source lang="javascript">
<syntaxhighlight lang="javascript">
switch (式) {
switch (式) {
case 値1 :
case 値1 :
243 行 243 行
文x]
文x]
}
}
</syntaxhighlight>
</source>
switch文に与えられた式に一致するcase句の値を上から順に厳密一致厳密比較演算子で評価され、true を返すcase句に対応する文が実行され、'''break文などの中断制御文が見つからない限り次の文が実行されます'''。
switch文に与えられた式に一致するcase句の値を上から順に厳密一致厳密比較演算子で評価され、true を返すcase句に対応する文が実行され、'''break文などの中断制御文が見つからない限り次の文が実行されます'''。


250 行 250 行
この為、式に対応する範囲や正規表現を直接的に表現することはできません。
この為、式に対応する範囲や正規表現を直接的に表現することはできません。
この制限はややトリッキーな方法で回避できます。
この制限はややトリッキーな方法で回避できます。
<source lang="javascript" highlight=3 line>
<syntaxhighlight lang="javascript" highlight=3 line>
let age = prompt("年齢は?"),
let age = prompt("年齢は?"),
text = "";
text = "";
261 行 261 行
}
}
console.log(text);
console.log(text);
</syntaxhighlight>
</source>
ポイントは
ポイントは
<source lang="javascript" start=3 highlight=1 line>
<syntaxhighlight lang="javascript" start=3 highlight=1 line>
switch (true) {
switch (true) {
</syntaxhighlight>
</source>
と式として true を与えているところで
と式として true を与えているところで
真となっている式を持ったケース節を上から探す
真となっている式を持ったケース節を上から探す
274 行 274 行
いよいよループの登場です。'''[[w:while文|while文]]'''(ホワイルぶん、''while statement'')は条件が真である間、文を実行しつづけます。
いよいよループの登場です。'''[[w:while文|while文]]'''(ホワイルぶん、''while statement'')は条件が真である間、文を実行しつづけます。


<source lang="javascript">
<syntaxhighlight lang="javascript">
let i = 0;
let i = 0;
while (i < 10) {
while (i < 10) {
280 行 280 行
i++;
i++;
}
}
</syntaxhighlight>
</source>


''i''はinteger(整数)の頭文字です。このプログラムはまず、
''i''はinteger(整数)の頭文字です。このプログラムはまず、
293 行 293 行


=== while 文の構文 ===
=== while 文の構文 ===
<source lang="javascript">
<syntaxhighlight lang="javascript">
while (式)
while (式)
</syntaxhighlight>
</source>
while文に与えられた式が truthy の間、繰り返し文を実行します。
while文に与えられた式が truthy の間、繰り返し文を実行します。


302 行 302 行
'''[[w:do-while文|do-while文]]'''(ドゥ・ホワイル文、''do-while statement'')は、まずdo文のブロックを実行し、次にwhile文の条件式を確認してループします。次のプログラムは0から9までの数字を表示します。
'''[[w:do-while文|do-while文]]'''(ドゥ・ホワイル文、''do-while statement'')は、まずdo文のブロックを実行し、次にwhile文の条件式を確認してループします。次のプログラムは0から9までの数字を表示します。


<source lang="javascript">
<syntaxhighlight lang="javascript">
let i = 0;
let i = 0;
do {
do {
308 行 308 行
i++;
i++;
} while (i < 10);
} while (i < 10);
</syntaxhighlight>
</source>


=== do-while 文の構文 ===
=== do-while 文の構文 ===
<source lang="javascript">
<syntaxhighlight lang="javascript">
do
do
while (式)
while (式)
</syntaxhighlight>
</source>
まず文を無条件に実行し、while文に与えられた式が truthy の間、繰り返し文を実行します。
まず文を無条件に実行し、while文に与えられた式が truthy の間、繰り返し文を実行します。


324 行 324 行
次のプログラムは0から9までの数字を表示します。
次のプログラムは0から9までの数字を表示します。


<source lang="javascript">
<syntaxhighlight lang="javascript">
for (let i = 0; i < 10; i++) {
for (let i = 0; i < 10; i++) {
console.log(i);
console.log(i);
}
}
</syntaxhighlight>
</source>


最初の式、let ''i'' = 0はループに入る前に一度だけ実行されます。
最初の式、let ''i'' = 0はループに入る前に一度だけ実行されます。
336 行 336 行
結果、''i'' < 10がtruthyである間、ブロックの実行と変数の更新が行われます。
結果、''i'' < 10がtruthyである間、ブロックの実行と変数の更新が行われます。


<source lang="javascript">
<syntaxhighlight lang="javascript">
const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
for (let i = 0, len = array.length; i < len; i++) {
for (let i = 0, len = array.length; i < len; i++) {
console.log(array[i]);
console.log(array[i]);
}
}
</syntaxhighlight>
</source>


ブロック文は文の特殊なケースで単文でももちろん有効です<ref>文 ⊇ ブロック文</ref>。
ブロック文は文の特殊なケースで単文でももちろん有効です<ref>文 ⊇ ブロック文</ref>。


<source lang="javascript">
<syntaxhighlight lang="javascript">
const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
for (let i = 0, len = array.length; i < len; i++)
for (let i = 0, len = array.length; i < len; i++)
console.log(array[i]);
console.log(array[i]);
</syntaxhighlight>
</source>


後置インクリメント演算子は変数の値を1増やし、増やす前の値を返すので、次のように書けます。
後置インクリメント演算子は変数の値を1増やし、増やす前の値を返すので、次のように書けます。


<source lang="javascript">
<syntaxhighlight lang="javascript">
const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
for (let i = 0, len = array.length: i < len; console.log(array[i++]))
for (let i = 0, len = array.length: i < len; console.log(array[i++]))
;
;
</syntaxhighlight>
</source>


このような書き方を好み人もいますが、文意を汲むなら...
このような書き方を好み人もいますが、文意を汲むなら...
<source lang="javascript">
<syntaxhighlight lang="javascript">
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ].forEach(x => console.log(x));
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ].forEach(x => console.log(x));
</syntaxhighlight>
</source>
のような、iterableオブジェクト<ref>この場合は Array オブジェクト</ref>の[[JavaScript/イテレーションメソッド|イテレーションメソッド]]を使うことも検討に値します。
のような、iterableオブジェクト<ref>この場合は Array オブジェクト</ref>の[[JavaScript/イテレーションメソッド|イテレーションメソッド]]を使うことも検討に値します。


=== for 文の構文 ===
=== for 文の構文 ===
<source lang="javascript">
<syntaxhighlight lang="javascript">
for ( 式1; 式2; 式3)
for ( 式1; 式2; 式3)
</syntaxhighlight>
</source>
* 式1を評価します
* 式1を評価します
* 式2が turuthy な間、以下を繰り返します
* 式2が turuthy な間、以下を繰り返します
378 行 378 行
== for-in ==
== for-in ==
for-in 文は、オブジェクトのプロパティのうちキーが文字列で列挙可能なもの全てに反復処理を行います。
for-in 文は、オブジェクトのプロパティのうちキーが文字列で列挙可能なもの全てに反復処理を行います。
<source lang="javascript">
<syntaxhighlight lang="javascript">
const obj = { x: 2, y: 3, z: 5 };
const obj = { x: 2, y: 3, z: 5 };


387 行 387 行
// y: 3
// y: 3
// z: 5
// z: 5
</syntaxhighlight>
</source>


== for-of ==
== for-of ==
for-of 文は、Iterableオブジェクト(たとえば String Array や NodeList)に対して、反復処理を行います<ref>ES2015で追加</ref>。
for-of 文は、Iterableオブジェクト(たとえば String Array や NodeList)に対して、反復処理を行います<ref>ES2015で追加</ref>。


<source lang="javascript" line>
<syntaxhighlight lang="javascript" line>
const ary = [..."XYZ"];
const ary = [..."XYZ"];


401 行 401 行
// Y
// Y
// Z
// Z
</syntaxhighlight>
</source>


Iterableでないオブジェクトが右の項に与えらてた場合、TypeError が throw されます。
Iterableでないオブジェクトが右の項に与えらてた場合、TypeError が throw されます。
<source lang="javascript" highlight=3 line>
<syntaxhighlight lang="javascript" highlight=3 line>
const obj = { a: 0, b: 1, c: 2};
const obj = { a: 0, b: 1, c: 2};


410 行 410 行
console.log(el);
console.log(el);
}
}
</syntaxhighlight>
</source>
Object はItableではないので
Object はItableではないので
TypeError: obj is not iterable
TypeError: obj is not iterable
417 行 417 行
== for await-of ==
== for await-of ==
for await-of 文は、非同期関数用の for-of です。
for await-of 文は、非同期関数用の for-of です。
<source lang="javascript">
<syntaxhighlight lang="javascript">
async function* asyncShift() {
async function* asyncShift() {
for (let i = 1, len = 2 ** 16; i < len; yield i <<= 3)
for (let i = 1, len = 2 ** 16; i < len; yield i <<= 3)
434 行 434 行
// 32768
// 32768
// 262144
// 262144
</syntaxhighlight>
</source>


== for each-in ==
== for each-in ==
461 行 461 行
次のプログラムは''i''が5になった時点でfor文のループを抜けるので、0から4までの数字を表示します。
次のプログラムは''i''が5になった時点でfor文のループを抜けるので、0から4までの数字を表示します。


<source lang="javascript">
<syntaxhighlight lang="javascript">
for (let i = 0; i < 10; i++) {
for (let i = 0; i < 10; i++) {
if (i == 5)
if (i == 5)
467 行 467 行
console.log(i);
console.log(i);
}
}
</syntaxhighlight>
</source>


== continue ==
== continue ==
473 行 473 行
次のプログラムは0から9までの数字のうち3の倍数だけ表示します。
次のプログラムは0から9までの数字のうち3の倍数だけ表示します。


<source lang="javascript">
<syntaxhighlight lang="javascript">
for (let i = 0; i < 10; i++) {
for (let i = 0; i < 10; i++) {
if (i % 3)
if (i % 3)
479 行 479 行
console.log(i);
console.log(i);
}
}
</syntaxhighlight>
</source>


== ラベル ==
== ラベル ==
ラベルを使用すると深いループを一気に抜けることができます。
ラベルを使用すると深いループを一気に抜けることができます。


<source lang="javascript">
<syntaxhighlight lang="javascript">
LOOP:
LOOP:
for (let x = 0; x < 10; x++) {
for (let x = 0; x < 10; x++) {
493 行 493 行
}
}
}
}
</syntaxhighlight>
</source>


{{コラム|URLが有効なJavaScript?|
{{コラム|URLが有効なJavaScript?|
次は有効な JavaScript のコードです。
次は有効な JavaScript のコードです。


<source lang="javascript" highlight=="1" line>
<syntaxhighlight lang="javascript" highlight=="1" line>
https://ja.wikibooks.org/
https://ja.wikibooks.org/
for (let i = 0; i < 3; i++) {
for (let i = 0; i < 3; i++) {
console.log(i);
console.log(i);
}
}
</syntaxhighlight>
</source>
1行目の URL がエラーになりません。
1行目の URL がエラーになりません。



2021年6月17日 (木) 17:49時点における版

制御構造(せいぎょこうぞう、control flow)とは、「順次」「分岐」「反復」という基本的な処理のことを言います。

概要

次のプログラムは、、

  • nが0より小さいときには「負の数」
  • nが0より大きいときには「正の数」
  • いづれにもあてはまらないなら(つまり nが0、あるいは数値に暗黙の変換ができないときには)「0」

と表示します。

let n = 0;

if (n < 0) {
    console.log("負の数");
}
else if (n > 0) {
    console.log("正の数");
}
else {
    console.log("0");
}

この様な、分岐を始めとする制御構造はプログラミングを行う上で欠かせません。

さあ、この章で学んで行きましょう。

if-else

if文(イフぶん、if statement)は「もし〜ならば」を表す制御構文(条件構文)です。 if文では()の中に書かれた条件が truthy であるとき続く文が実行されます。 次のプログラムは、n < 0(nが0より小さい)という条件が真であるときのみ「負の数」と表示します。

let n = -1;

if (n < 0) {
    console.log("負の数");
}

if文のあとにelse節(エルスせつ、else clause)を置くと、else節の文はif文の条件が falsy であるときのみ実行されます。 次のプログラムは、n < 0(nが0より小さい)という条件が真であれば「負の数」、さもなくば(nが0以上あるいはNaN(略 ならば)「自然数」と表示します[1]

let n = 0;

if (n < 0) {
    console.log("負の数");
}
else {
    console.log("自然数");
}

if文とelse節をあわせてif/else文と呼びます。else節は必ず直前のif文に対応するので、if文とelse節の間に余計な文を入れることはできません。 if/else文は次のように何個もつらねることができます。

let n = 0;

if (n < 0) {
    console.log("負の数");
}
else if (n > 0) {
    console.log("正の数");
}
else {
    console.log("0");
}

このプログラムはn < 0ならば「負の数」、そうでなくn > 0ならば「正の数」、そうでもないならば「0」と表示します。 else ifという部分に注目してください。 何通りもの条件で処理を分岐したい場合は、このelse ifを何個も増やしていくことになります。 if文やelse節の文はブロックである必要はありません。 単文(1つの文)しか入っていない場合は、次のように書いても同じことです。

let n = 0;

if (n < 0)
    console.log("負の数");
else if (n > 0)
    console.log("正の数");
else
    console.log("0");

なお、この場合は条件演算子を用いて簡潔に書けます。

let n = 0;

console.log(n < 0 ? "負の数"
          : n > 0 ? "正の数"
          :         "0");

if文の条件式はすべてtrueかfalseの真偽値として評価されます。たとえば、数値の0は真偽値に変換するとfalseになるので[2]、次のif文のブロックは絶対に実行されません(デッドコード)。

if (0) {
    // たどりつけない
}
0以外にもfailyが
他の言語(例えばC言語)では、nが0に等しいかどうかは
if (n == 0) { /* ... */ }

のほかに

if (!n) { /* ... */ }

と書けます、同様に nが0に等しくないかどうかは

if (n != 0) { /* ... */ }
のほかに
if (n) { /* ... */ }

とも書けます。

しかし、JavaScript では「0以外にも falsy な値がある」(例えば !"" は真になる)ので上記のC言語流のブールコンテキストのイデオムは使えません。 JavaScriptではnが0に等しいかどうかは n === 0 のように ===(厳密比較演算子)を使います。 === は==(比較演算子)とは異なり暗黙の型変換は行われず厳密に(この場合は 0 と)等しいかを評価します。


  • 例題

整数の偶奇判別プログラムを書け。

  • 解答

if/else文を用いる場合は、

if (n % 2 == 0) {
    console.log("偶数");
}
else {
    console.log("奇数");
}

または

if (n % 2) {
    console.log("奇数");
}
else {
    console.log("偶数");
}

条件演算子を用いる場合は、

console.log(n % 2 == 0 ? "偶数"
                       : "奇数");

または

console.log(n % 2 ? "奇数"
                  : "偶数");

または

console.log((n % 2 ? "奇"
                   : "偶") + "数");

または

console.log("偶奇"[n % 2] + "数");

など。

if-else 文の構文

if (条件式)
    文1
[else
    文2]

[から]までは省略可能を意味し、この場合は「else節は省略可能」を意味します。

switch

switch文(スイッチぶん、switch statement)は、if/else文を何個もつらねて書くことが冗長な場合に用いられます。

if (keyCode == 37) {
    console.log("←");
}
else if (keyCode == 38) {
    console.log("↑");
}
else if (keyCode == 39) {
    console.log("→");
}
else if (keyCode == 40) {
    console.log("↓");
}
else {
    console.log("?");
}

これはswitch文を使って次のように書くことができます。

switch (keyCode) {
case 37:
    console.log("←");
    break;
case 38:
    console.log("↑");
    break;
case 39:
    console.log("→");
    break;
case 40:
    console.log("↓");
    break;
default:
    console.log("?");
}

必ずcase節の最後にbreak文を書くのを忘れないでください。 なお、たいていのケースではswitch文を使わなくても、連想配列を応用したディスパッチテーブルで事足ります。 switch文はここぞというときに使ってください[3]

console.log({ 37: "←", 38: "↑", 39: "→", 40: "↓" }[keyCode] || "?");

switch 文の構文

switch () {
case 値1 :
    文1
case 値2 :
    文2
   :
   :
case 値n :
    文n
[default :
    文x]
}

switch文に与えられた式に一致するcase句の値を上から順に厳密一致厳密比較演算子で評価され、true を返すcase句に対応する文が実行され、break文などの中断制御文が見つからない限り次の文が実行されます

switch文の限界と限界突破

swicth文は、上記の通り与えられた式と厳密に一致するケースに対応する文を実行します。 この為、式に対応する範囲や正規表現を直接的に表現することはできません。 この制限はややトリッキーな方法で回避できます。

let age = prompt("年齢は?"),
  text = "";
switch (true) {
case age <  3: text = "baby";         break;
case age <  7: text = "little child"; break;
case age < 13: text = "child";        break;
case age < 18: text = "youth";        break;
default :      text = "adult";        break;
}
console.log(text);

ポイントは

switch (true) {

と式として true を与えているところで

真となっている式を持ったケース節を上から探す

と言う動作を悪用利用しています。


while

いよいよループの登場です。while文(ホワイルぶん、while statement)は条件が真である間、文を実行しつづけます。

let i = 0;
while (i < 10) {
    console.log(i);
    i++;
}

iはinteger(整数)の頭文字です。このプログラムはまず、

  • 1行目で変数iに0を代入しています。
  • 次にi < 10がtrueでれば以下を実行します(そうでなければ、このwhile文の次に進みます)。
    • iを表示します
    • iを1増やします。

10回ループが回るとiが10になり、i < 10がfalseになるのでループを抜けます。 このようにwhile文はi < 10がtrueである間、ブロックを実行しつづけます。 このようにして、プログラムは0から9までの数字を表示します(10に達するとループから脱出します)。

while 文の構文

while ()
    

while文に与えられた式が truthy の間、繰り返し文を実行します。

do-while

do-while文(ドゥ・ホワイル文、do-while statement)は、まずdo文のブロックを実行し、次にwhile文の条件式を確認してループします。次のプログラムは0から9までの数字を表示します。

let i = 0;
do {
    console.log(i);
    i++;
} while (i < 10);

do-while 文の構文

do
    
while ()

まず文を無条件に実行し、while文に与えられた式が truthy の間、繰り返し文を実行します。

for

for文(フォー文、for statement)は、いわゆるC言語スタイルのfor文です。 let i = 0のような変数の初期化と、i < 10のような条件式と、i++のような変数の更新を一行で書く制御構文です。 JavaScriptではwhile文やdo-while文はあまり使われませんが、for文はループを簡潔に書けるので非常に重宝します。 次のプログラムは0から9までの数字を表示します。

for (let i = 0; i < 10; i++) {
    console.log(i);
}

最初の式、let i = 0はループに入る前に一度だけ実行されます。 二番目の式、i < 10がtruthyならばブロックを実行します。 三番目の式i++を実行して再び条件式に戻ります。

結果、i < 10がtruthyである間、ブロックの実行と変数の更新が行われます。

const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
for (let i = 0, len = array.length; i < len; i++) {
    console.log(array[i]);
}

ブロック文は文の特殊なケースで単文でももちろん有効です[4]

const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
for (let i = 0, len = array.length; i < len; i++)
    console.log(array[i]);

後置インクリメント演算子は変数の値を1増やし、増やす前の値を返すので、次のように書けます。

const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
for (let i = 0, len = array.length: i < len; console.log(array[i++]))
  ;

このような書き方を好み人もいますが、文意を汲むなら...

[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ].forEach(x => console.log(x));

のような、iterableオブジェクト[5]イテレーションメソッドを使うことも検討に値します。

for 文の構文

for ( 式1; 式2; 式3)
    
  • 式1を評価します
  • 式2が turuthy な間、以下を繰り返します
    • 文 を実行します
    • 式3 を評価します

for-in

for-in 文は、オブジェクトのプロパティのうちキーが文字列で列挙可能なもの全てに反復処理を行います。

const obj = { x: 2, y: 3, z: 5 };

for (const prop in obj) {
    console.log(`${prop}: ${obj[prop]}`);
}
// x: 2
// y: 3
// z: 5

for-of

for-of 文は、Iterableオブジェクト(たとえば String Array や NodeList)に対して、反復処理を行います[6]

const ary = [..."XYZ"];

for (const el of ary) {
    console.log(el);
}
// X
// Y
// Z

Iterableでないオブジェクトが右の項に与えらてた場合、TypeError が throw されます。

const obj = { a: 0, b: 1, c: 2};

for (const el of obj) {
    console.log(el);
}

Object はItableではないので

TypeError: obj is not iterable

となる。

for await-of

for await-of 文は、非同期関数用の for-of です。

async function* asyncShift() {
  for (let i = 1, len = 2 ** 16; i < len; yield i <<= 3)
    ;
}

(async function() {
  for await (const num of asyncShift()) {
    console.log(num);
  }
})();
// 8
// 64
// 512
// 4096
// 32768
// 262144

for each-in

for each-in 文はJavaScript 1.6でECMAScript for XML(E4X)のサポートの一環で導入されましたが、E4Xの廃止を受け非推奨を経て廃止されました。 下のプログラム例もモダンブラウザでは SyntaxError となります。for … of 文を使うようにして下さい。
JavaScript 1.6で追加されたfor each-in文はオブジェクトの値を順番に取り出して反復処理します。

var sales = <sales vendor="John">
    <item type="peas" price="4" quantity="6"/>
    <item type="carrot" price="3" quantity="10"/>
    <item type="chips" price="5" quantity="3"/>
  </sales>;
for each(var price in sales..@price) {
    console.log(price);
}
/*
 4
 3
 5
 */

break

break文(ブレーク文、break statement)はループまたはswitch文を途中で抜けます。 次のプログラムはiが5になった時点でfor文のループを抜けるので、0から4までの数字を表示します。

for (let i = 0; i < 10; i++) {
    if (i == 5)
        break;
    console.log(i);
}

continue

continue文(コンティニュー文、continue statement)はループを次に進めます。 次のプログラムは0から9までの数字のうち3の倍数だけ表示します。

for (let i = 0; i < 10; i++) {
    if (i % 3)
        continue;
    console.log(i);
}

ラベル

ラベルを使用すると深いループを一気に抜けることができます。

LOOP:
for (let x = 0; x < 10; x++) {
    for (let y = 0; y < 10; y++) {
        if (y == 5)
            break LOOP;
        console.log([ x, y ]);
    }
}
URLが有効なJavaScript?

次は有効な JavaScript のコードです。

https://ja.wikibooks.org/
for (let i = 0; i < 3; i++) {
    console.log(i);
}

1行目の URL がエラーになりません。

この行は

識別名 https のラベル と // で始まる単行コメント

と解されます。

重大なバグにはなりそうにないですが、モヤモヤしますね。


その他の制御文

with文

曖昧さを持ち込むためwith 文の使用は推奨されない。 また、strictモードでは SyntaxError となる。

with文の用途は、実際のコードを見ると良い。次の2つの関数は同じ意味である。

function math1(){
  1th.ceil(10.5));	// 小数点切り上げの値を表示
  console.log(Math.PI);	// 円周率πを表示
}

function math2(){
  with (Math){
    console.log(ceil(10.5));	// 小数点切り上げの値を表示
    console.log(PI);	// 円周率πを表示
  }
}
math1();
math2();

この様に、あらかじめオブジェクトをwith文で指定することで、それに続くブロックの間では、オブジェクトの名前を省略することが出来る。 これは Pascal などの言語から採用されたものである。 with は、with により修飾名が省略されたことにより識別子に曖昧さを持ち込む事で、意図しないプロパティが使われるなど問題を生じることが知られており、with 文の使用は推奨されない。 また、strictモードでは SyntaxError となる。


脚注

  1. ^ 計算機科学では一般に0を自然数に含め、曖昧さを避けたいときは非負整数とも言います
  2. ^ falsy
  3. ^ JavaScriptのswitch文は、動的なのに静的なC言語の構文を倣ったのでコラム:switch文の限界と限界突破の様なハックを使わない限り恩恵を受けられません。
  4. ^ 文 ⊇ ブロック文
  5. ^ この場合は Array オブジェクト
  6. ^ ES2015で追加

外部リンク

このページ「JavaScript/制御構造」は、まだ書きかけです。加筆・訂正など、協力いただける皆様の編集を心からお待ちしております。また、ご意見などがありましたら、お気軽にトークページへどうぞ。