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

削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
語尾の統一
タグ: 2017年版ソースエディター
cleanup
タグ: 2017年版ソースエディター
1 行
{{Nav}}
'''[[w:制御構造|制御構造]]'''(せいぎょこうぞう、( ''control flow'' )とは、「順次」「[[#分岐|分岐]]」「[[#反復|反復]]」という基本的な処理実行順序の制御のことを言います。
 
== 概要分岐 ==
次のプログラムは、、
* ''n''が0より小さいときには「負の数」
* ''n''が0より大きいときには「正の数」
* いづれにもあてはまらないなら(つまり ''n''が0、あるいは数値に暗黙変換ができないときには0
* いづれにもあてはまらないなら、''n''自身を表示します。
 
;[https://paiza.io/projects/PVQmLtgKSbojqVJ52Z7FLA?language=javascript 例]:<syntaxhighlight lang=js line>
"use strict";
 
:<syntaxhighlight lang="javascript">
const n = 0 / 0;
 
if (n < 0) {
console.log("負の数");
} else if (n > 0) {
}
console.log("正の数");
else if (n > 0) {
} else if (n > 0) {
console.log("正の数");
console.log("零");
}
} else if (n > 0) {
console.log("零"n);
}
else {
console.log(n);
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
NaN
</syntaxhighlight>
: <code>0 / 0</code>は、除数がゼロであると考えれば無限大ですが、被除数がゼロと考えるとゼロというパラドックス持ちで、ISO/IEC/IEEE 60559:2011 ではこのケースを NaN 非数とします。
 
この様な、分岐を始めとする制御構造はプログラミングを行う上で欠かせません。
 
=== if-else ===
さあ、この章で学んで行きましょう。
'''[[w:if文|if文]]'''( ''if statement'' )は「もし〜ならば」を表す条件分岐構文です。
 
== if-else ==
'''[[w:if文|if文]]'''(イフぶん、''if statement'')は「もし〜ならば」を表す制御構文(条件構文)です。
if文では{{code|()}}の中に書かれた条件が [[JavaScript/truthy|truthy]] であるとき続く文が実行されます。
次のプログラムは、''n'' < 0(''n''が0より小さい)という条件が真であるときのみ「負の数」と表示します。
 
;[https://paiza.io/projects/MH-qBPF-5NoFfr8RE9pNgw?language=javascript 例]:<syntaxhighlight lang="javascript"js line>
"use strict";
const n = -1;
 
const n = -1;
if (n < 0) {
console.log("負の数");
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
負の数
</syntaxhighlight>
 
if文のあとに'''else節'''( ''else clause'' )を置くと、else節の文はif文の条件が [[JavaScript/falsy|falsy]] であるときのみ実行されます。
次のプログラムは、''n'' < 0(''n''が0より小さい)という条件が真であれば「負の数」、さもなくば「自然数」と表示します<ref>計算機科学では一般に0を自然数に含め、曖昧さを避けたいときは非負整数とも言います</ref>。
 
;[https://paiza.io/projects/4xFIs20boohxUskXETRF5A?language=javascript 例]:<syntaxhighlight lang=js line>
if文のあとに'''else節'''(エルスせつ、''else clause'')を置くと、else節の文はif文の条件が [[JavaScript/falsy|falsy]] であるときのみ実行されます。
"use strict";
次のプログラムは、''n'' < 0(''n''が0より小さい)という条件が真であれば「負の数」、さもなくば(''n''が0以上あるいはNaN(略 ならば)「自然数」と表示します<ref>計算機科学では一般に0を自然数に含め、曖昧さを避けたいときは非負整数とも言います</ref>。
 
:<syntaxhighlight lang="javascript">
const n = 0;
 
if (n < 0) {
console.log("負の数");
} else {
}
console.log("自然数");
else {
console.log("自然数");
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
自然数
</syntaxhighlight>
 
if文とelse節をあわせてif/else文と呼びます。else節は必ず直前のif文に対応するので、if文とelse節の間に余計な文を入れることはできません
 
if/else文は次のように何個もつらねることができます。
else節の文をif文とすることで、次のように何個もつらねることができます。
 
;[https://paiza.io/projects/eFR9IgcwfDGYVdzdSraJsg?language=javascript 例]:<syntaxhighlight lang=js line>
"use strict";
 
:<syntaxhighlight lang="javascript">
const n = 0;
 
if (n < 0) {
console.log("負の数");
} else if (n > 0) {
}
console.log("正の数");
else if (n > 0) {
} else if (n == 0) {
console.log("正の数");
console.log("零");
}
} else if (n == 0) {
console.log("零"n);
}
else {
console.log(n);
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
</syntaxhighlight>
: このプログラムは''n'' < 0ならば「負の数」、そうでなく''n'' > 0ならば「正の数」、そうでなく''n'' == 0ならば「零」、そうでもないならば n の値が表示されます。
: <code>else if</code>という部分に注目してください。
: 何通りもの条件で処理を分岐したい場合は、このelse ifを何個も増やしていくことになります。
: if文やelse節の文はブロックである必要はありません。
: 単文(1つの文)しか入っていない場合は、次のように書いても同じことです。
 
;例:<syntaxhighlight lang=js line>
このプログラムは''n'' < 0ならば「負の数」、そうでなく''n'' > 0ならば「正の数」、そうでなく''n'' == 0ならば「零」、そうでもないならば n の値が表示されます。
"use strict";
<code>else if</code>という部分に注目してください。
何通りもの条件で処理を分岐したい場合は、このelse ifを何個も増やしていくことになります。
if文やelse節の文はブロックである必要はありません。
単文(1つの文)しか入っていない場合は、次のように書いても同じことです。
 
:<syntaxhighlight lang="javascript">
const n = 0;
if (n < 0) console.log("負の数");
 
else if (n <> 0) console.log("正の数");
else if (n == 0) console.log("負の数");
else if console.log(n > 0);
console.log("正の数");
else if (n == 0)
console.log("零");
else
console.log(n);
</syntaxhighlight>
 
なお、この場合は条件演算子を用いて簡潔に書くことができます。
 
;例:<syntaxhighlight lang="javascript"js line>
"use strict";
const n = 0;
 
const n = 0;
console.log(n < 0 ? "負の数"
: n > 0 ? "正の数"
: n == 0 ? "零"
: n);
</syntaxhighlight>
109 ⟶ 115行目:
if文の条件式はすべてtrueかfalseの[[JavaScript/Boolean|真偽値]]として評価されます。たとえば、数値の0は真偽値に変換するとfalseになるので<ref>falsy</ref>、次のif文のブロックは絶対に実行されません([[w:到達不能コード|デッドコード]])。
 
:<syntaxhighlight lang="javascript"js line>
if (0) {
// たどりつけ着くことはない
}
</syntaxhighlight>
134 ⟶ 140行目:
if/else文を用いる場合は、
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
if (n % 2 == 0) {
console.log("偶数");
} else {
}
console.log("奇数");
else {
console.log("奇数");
}
</syntaxhighlight>
145 ⟶ 152行目:
または
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
if (n % 2) {
console.log("奇数");
} else {
}
console.log("偶数");
else {
console.log("偶数");
}
</syntaxhighlight>
156 ⟶ 164行目:
条件演算子を用いる場合は、
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
console.log(n % 2 == 0 ? "偶数"
: "奇数");
163 ⟶ 173行目:
または
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
console.log(n % 2 ? "奇数"
: "偶数");
170 ⟶ 182行目:
または
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
console.log((n % 2 ? "奇"
: "偶") + "数");
176 ⟶ 190行目:
または
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
console.log("偶奇"[n % 2] + "数");
</syntaxhighlight>
182 ⟶ 198行目:
 
=== if-else 文の構文===
:<syntaxhighlight lang="javascript"js>
if ( 条件式 ) 文1 [ else 文2 ]
文1
[else
文2]
</syntaxhighlight>
{{code|[}}から{{code|]}}までは省略可能を意味し、この場合は「else節は省略可能」を意味します。
 
=== switch ===
'''[[w:switch文|switch文]]'''(スイッチぶん、( ''switch statement'' )は、if/else文を何個もつらねて書くことが冗長な場合にもちいられます。
 
:<syntaxhighlight lang=js line>
"use strict";
 
:<syntaxhighlight lang="javascript">
if (keyCode == 37) {
console.log("←");
} else if (keyCode == 38) {
}
console.log("↑");
else if (keyCode == 38) {
} else if (keyCode == 39) {
console.log("↑");
console.log("→");
}
} else if (keyCode == 3940) {
console.log("");
} else {
}
console.log("?");
else if (keyCode == 40) {
console.log("↓");
}
else {
console.log("?");
}
</syntaxhighlight>
 
これはswitch文を使って次のように書くことができます。
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
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("?");
}
}</syntaxhighlight>
</syntaxhighlight>
 
必ずcase節の最後にbreak文を書くのを忘れないでください。
234 ⟶ 248行目:
switch文はここぞというときに使ってください<ref>JavaScriptのswitch文は、動的なのに静的なC言語の構文を倣ったので'''[[#switch文の限界と限界突破|コラム:switch文の限界と限界突破]]'''の様なハックを使わない限り恩恵を受けられません。</ref>。
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
console.log({ 37: "←", 38: "↑", 39: "→", 40: "↓" }[keyCode] || "?");
 
console.log(
{
37: "←",
38: "↑",
39: "→",
40: "↓"
}[keyCode] || "?"
);
</syntaxhighlight>
 
=== switch 文の構文===
:<syntaxhighlight lang="javascript"js>
switch (式) {
case 値1 :
245 ⟶ 268行目:
case 値2 :
文2
:
:
case 値n :
文n
259 ⟶ 282行目:
この為、式に対応する範囲や正規表現を直接的に表現することはできません。
この制限はややトリッキーな方法で回避できます。
:<syntaxhighlight lang="javascript"js highlight=3 line>
let age = prompt("年齢は?"),
text = "";
272 ⟶ 295行目:
</syntaxhighlight>
ポイントは
:<syntaxhighlight lang="javascript"js start=3 highlight=1 line>
switch (true) {
</syntaxhighlight>
280 ⟶ 303行目:
}}
 
== while反復 ==
=== while ===
いよいよループの登場です。'''[[w:while文|while文]]'''(ホワイルぶん、''while statement'')は条件が真である間、文を実行しつづけます。
いよいよループの登場です。'''[[w:while文|while文]]'''( ''while statement'' )は条件が真である間、文を実行しつづけます。
 
;[https://paiza.io/projects/rmb98IyjUuJlXVceEotPtw?language=javascript 例]:<syntaxhighlight lang=js line>
"use strict";
 
:<syntaxhighlight lang="javascript">
let i = 0;
while (i < 10) {
console.log(i);
i++;
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
 
0
''i''はinteger(整数)の頭文字です。このプログラムはまず、
1
* 1行目で変数''i''に0を代入しています。
2
*次に''i'' < 10がtrueでれば以下を実行します(そうでなければ、このwhile文の次に進みます)。
3
** ''i''を表示します
4
** ''i''を1増やします。
5
6
7
8
9
</syntaxhighlight>
# strictモードは常に使うべきです。
# &nbsp;
# 変数''i''に0を代入
# ''i'' < 10がtrueでれば以下を実行します
#: そうでなければ、このwhile文の次に進みます
# ''i''を表示します
# ''i''を1増やします。
 
10回ループが回ると''i''が10になり、''i'' < 10がfalseになるのでループを抜けます。
302 ⟶ 341行目:
 
=== while 文の構文 ===
:<syntaxhighlight lang="javascript"js>
while ( )
</syntaxhighlight>
while文に与えられた式が truthy の間、繰り返し文を実行します。
 
=== do-while ===
'''[[w:do-while文|do-while文]]'''(ドゥ・ホワイル文、( ''do-while statement'' )は、まずdo文のブロックを実行し、次にwhile文の条件式を確認してループします。次のプログラムは0から9までの数字を表示します。
 
:<syntaxhighlight lang="javascript"js line>
let i = 0;
do {
320 ⟶ 358行目:
 
=== do-while 文の構文 ===
:<syntaxhighlight lang="javascript"js>
do 文 while ( 式 )
do
while (式)
</syntaxhighlight>
まず文を無条件に実行し、while文に与えられた式が truthy の間、繰り返し文を実行します。
 
=== for ===
'''[[w:文|for文]]'''(フォー文、( ''for statement'' )は、いわゆる[[C言語/制御文#for文|C言語スタイルのfor文]]です。
let ''i'' = 0のような変数の初期化と、''i'' < 10のような条件式と、''i''++のような変数の更新を一行で書く制御構文です。
JavaScriptではwhile文やdo-while文はあまり使われませんが、for文はループを簡潔に書けるので非常に重宝します。
次のプログラムは0から9までの数字を表示します。
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
for (let i = 0; i < 10; i++) {
console.log(i);
}
</syntaxhighlight>
: 最初の項、let ''i'' = 0はループに入る前に一度だけ実行されます。
 
最初: 二番目の式、let ''i'' =< 0はループに入る前に一度だけ10がtruthyならばブロックを実行されます。
: 三番目の式''i'' < 10がtruthyならばブロック++を実行して再び条件式に戻ります。
三番目の式''i''++を実行して再び条件式に戻ります。
 
結果、''i'' < 10がtruthyである間、ブロックの実行と変数の更新が行われます。
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
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++) {
console.log(array[i]);
}
</syntaxhighlight>
354 ⟶ 393行目:
ブロック文は文の特殊なケースで単文でももちろん有効です<ref>文 ⊇ ブロック文</ref>。
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
const array = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
 
for (let i = 0, len = array.length; i < len; i++)
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(array[i]);
for (let i = 0, len = array.length; i < len; i++) console.log(array[i]);
</syntaxhighlight>
 
後置インクリメント演算子は変数の値を1増やし、増やす前の値を返すので、次のように書けます。
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
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++]))
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++]));
</syntaxhighlight>
 
このような書き方を好み人もいますが、文意を汲むなら...
:<syntaxhighlight lang="javascript"js line>
"use strict";
[ 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>
のような、iterableオブジェクト<ref>この場合は Array オブジェクト</ref>の[[JavaScript/イテレーションメソッド|イテレーションメソッド]]を使うことも検討に値します。
 
=== for 文の構文 ===
:<syntaxhighlight lang="javascript"js>
for ( 1 ; 式2 ; 式3 )
</syntaxhighlight>
* 1を評価します
* 式2が turuthy な間、以下を繰り返します
** 文 を実行します
385 ⟶ 427行目:
<!--スコープについて要加筆-->
 
=== for-in ===
for-in 文は、オブジェクトのプロパティのうちキーが文字列で列挙可能なもの全てに反復処理を行います。
;[https://paiza.io/projects/ZmkzUwnrzEgyff8eb60gEg?language=javascript 例]:<syntaxhighlight lang="javascript"js line>
"use strict";
const obj = { x: 2, y: 3, z: 5 };
 
const obj = {
x: 2,
y: 3,
z: 5
};
for (const prop in obj) {
console.log(`${prop}: ${obj[prop]}`);
}
</syntaxhighlight>
// x: 2
;実行結果:<syntaxhighlight lang=text>
// y: 3
// zx: 52
y: 3
z: 5
</syntaxhighlight>
 
=== for-of ===
for-of 文は、Iterableオブジェクト(たとえば String Array や NodeList)に対して、反復処理を行います<ref>ES2015で追加</ref>。
 
;[https://paiza.io/projects/GnxH5dTKhRA8Mcz24mIHTQ?language=javascript for-of]:<syntaxhighlight lang="javascript"js line>
"use strict";
const ary = [..."XYZ"];
 
const ary = [..."XYZ"];
for (const el of ary) {
console.log(el);
}
</syntaxhighlight>
// X
;実行結果:<syntaxhighlight lang=text>
// Y
X
// Z
Y
Z
</syntaxhighlight>
 
Iterableでないオブジェクトが右の項に与えらてた場合、TypeError が throw されます。
;Objectはfor-of不可:<syntaxhighlight lang="javascript"js highlight=3 line>
"use strict";
const obj = { a: 0, b: 1, c: 2};
 
const obj = {
a: 0,
b: 1,
c: 2
};
for (const el of obj) {
console.log(el);
}
</syntaxhighlight>
:Object はItableではないので
;実行時エラー:<syntaxhighlight lang="text">
/workspace/Main.js:8
for (const el of obj) {
^
 
TypeError: obj is not iterable
at Object.<anonymous> (/workspace/Main.js:8:18)
at Module._compile (node:internal/modules/cjs/loader:1126:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1180:10)
at Module.load (node:internal/modules/cjs/loader:1004:32)
at Function.Module._load (node:internal/modules/cjs/loader:839:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47
</syntaxhighlight>
:となります。
 
;[https://paiza.io/projects/8oFPy97Ozwg9nv4VPeWcTw?language=javascript for-ofとObjectの分割代入の併用]:<syntaxhighlight lang="javascript"js line>
"use strict";
const AddrBook = [
{
name: "tom",
postnumber: "420-2410",
age: 18
},
{
name: "joe",
postnumber: "420-0824",
age: 17
},
]
 
const AddrBook = [
{
name: "tom",
postnumber: "420-2410",
age: 18
},
{
name: "joe",
postnumber: "420-0824",
age: 17
}
];
for (const { name, age } of AddrBook) {
console.log(`${name}: ${age}`);
}
 
/** 同じコンセプトのArray::forEach */
AddrBook.forEach(({ name, age }) => console.log(`${name}: ${age}`));
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
tom: 18
joe: 17
454 ⟶ 523行目:
</syntaxhighlight>
 
=== for await-of ===
for await-of 文は、非同期関数用の for-of です。
;[https://paiza.io/projects/nvHmwLQTDhA1cKqZGsKpTg?language=javascript 例]:<syntaxhighlight lang="javascript"js line>
"use strict";
 
async function* asyncShift() {
for (let i = 1, len = 2 ** 16; i < len; yield (i <<= 3));
;
}
(async function () {
 
(async function() {
for await (const num of asyncShift()) {
console.log(num);
}
})();
</syntaxhighlight>
// 8
;実行結果:<syntaxhighlight lang=text>
// 64
8
// 512
64
// 4096
512
// 32768
4096
// 262144
32768
262144
</syntaxhighlight>
 
=== for each-in ===
for each-in 文はJavaScript 1.6で[[w:ECMAScript for XML|ECMAScript for XML]](E4X)のサポートの一環で導入されましたが、E4Xの廃止を受け非推奨を経て'''廃止'''されました。
下のプログラム例もモダンブラウザでは SyntaxError となります。[[#for … of|for … of]] 文を使うようにして下さい。<br>
JavaScript 1.6で追加されたfor each-in文はオブジェクトの値を順番に取り出して反復処理します。
 
:<syntaxhighlight lang="JavaScript"js line>
var sales = <sales vendor="John">
<item type="peas" price="4" quantity="6"/>
496 ⟶ 567行目:
</SyntaxHighlight>
 
== break反復制御 ==
反復処理中に、反復を中断したり、「次の」反復にすぐに移りたい場合があります。
'''[[w:break文|break文]]'''(ブレーク文、''break statement'')はループまたはswitch文を途中で抜けます。
このようなときは、反復制御構文を使います。
 
=== break ===
'''[[w:break文|break文]]'''( ''break statement'' )はループまたはswitch文を途中で抜けます。
次のプログラムは''i''が5になった時点でfor文のループを抜けるので、0から4までの数字を表示します。
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
for (let i = 0; i < 10; i++) {
if (i == 5) break;
console.log(i);
break;
console.log(i);
}
</syntaxhighlight>
 
=== continue ===
'''[[w:continue文|continue文]]'''(コンティニュー文、( ''continue statement'' )はループを次に進めます。
次のプログラムは0から9までの数字のうち3の倍数だけ表示します。
 
:<syntaxhighlight lang="javascript"js line>
"use strict";
 
for (let i = 0; i < 10; i++) {
if (i % 3) continue;
console.log(i);
continue;
console.log(i);
}
</syntaxhighlight>
 
=== ラベル ===
ラベルを使用すると深いループを一気に抜けることができます。
 
;ラベルの使用例:<syntaxhighlight lang="javascript"js line>
"use strict";
let LOOP = "Global variable"
 
let LOOP = "Global variable";
LOOP:
LOOP: for (let x = 0; x < 10; x++) {
for (let y = 0; y < 10; y++) {
if (y === 5) break LOOP;
console.log([x, y]);
break LOOP
}
console.log([x, y])
}
}
console.log(LOOP);
}
 
console.log(LOOP)
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
[ 0, 0 ]
[ 0, 1 ]
552 ⟶ 627行目:
次は有効な JavaScript のコードです。
 
;URLが有効なJavaScript?:<syntaxhighlight lang="javascript"js highlight=="13" line>
"use strict";
 
https://ja.wikibooks.org/
for (let i = 0; i < 3; i++) {
567 ⟶ 644行目:
}}
 
=== その他の制御文 ===
<!-- 関数呼び出しと return文はここに含めるべき? -->
 
577 ⟶ 654行目:
with文の用途は、実際のコードを見ると良い。次の2つの関数は同じ意味です。
 
;[https://paiza.io/projects/tEknwwCpEg4jt7y9lcNPTw?language=javascript withの使用例]:<syntaxhighlight lang="javascript"js line>
function math1() {
console.log(Math.ceil(10.5)); // 小数点切り上げの値を表示
console.log(Math.PI); // 円周率πを表示
}
 
function math2() {
with (Math) {
console.log(ceil(10.5)); // 小数点切り上げの値を表示
console.log(PI); // 円周率πを表示
}
}
math1();
math2();
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
11
3.141592653589793