第7章 JavaScriptの条件分岐処理入門
ウェブページに訪れたユーザーさんがフォームに入力した値に応じて異なる動作をさせたり、ショッピングカートの中の商品の合計金額に応じて送料を変えて表示したりするのを、条件に応じて処理を分岐するので「条件分岐処理」といいます。
このページでは、JavaScriptでの条件分岐処理の方法について解説します。
前回までの講座で、
- 第1章 JavaScriptでのブラウザ版VSCode入門
- 第2章 JavaScriptと蜜月の関係であるHTMLとCSS入門
- 第3章 JavaScriptの実行方法入門
- 第4章 JavaScriptの変数入門
- 第5章 JavaScriptの関数入門
- 第6章 JavaScriptのオブジェクト入門
について学びました。今回はそれらを一読された前提での続編になります。
目次
学習用コード
以下のindex.htmlとindex.jsファイルの内容をこの章の学習の出発点にします。
※ 一応これらファイルを自サーバーに準備してあります。必要な方はダウンロードして解凍してください。(ファイルの解凍方法は第1章のファイルの展開(解凍)方法で触れています)
第7章の学習用ファイル(chapter07.zip)をダウンロード
<!DOCTYPE html>
<html>
<head>
<title>タイトル</title>
</head>
<body>
<h1>見出し</h1>
<p id="danraku1">段落</p>
<script src="js/index.js"></script>
</body>
</html>
// サイコロの目の乱数を生成したい
let saikoro = Math.random() * 6 + 1;
// 小数点以下を切り捨て
saikoro = Math.floor(saikoro);
// 条件式が常にtrueになるのでこのconsole.log()は毎回実行される。
if (saikoro > 0) console.log("サイコロを振ると" + saikoro + "の目が出ました。");
// 2で割った余り(剰余)が0の時は偶数
if (saikoro % 2 === 0) console.log("そのサイコロの目は偶数です。");
// 2で割った余り(剰余)が1の時は奇数
if (saikoro % 2 === 1) console.log("そのサイコロの目は奇数です。");
if (saikoro % 2 === 0) console.log("くどいようですがサイコロの目は偶数です。");
else console.log("くどいようですがそのサイコロの目は奇数です。");
if (saikoro < 3) console.log("サイコロの目が3より小さかった。");
else if (saikoro <= 5) console.log("サイコロの目が3以上5以下だった。");
else console.log("サイコロの目が6だった。");
分岐処理の解説に「毎回異なるサイコロの出目」と「偶数・奇数判定」を使いたかったので、まずそれらを先に解説してから分岐処理の話に移行します。
JavaScriptでサイコロを振る方法
JavaScriptでサイコロを再現して、実行するたびに1から6までのいずれかのランダムな数を変数saikoroに格納するコードは、
// サイコロの目の乱数を生成したい
let saikoro = Math.random() * 6 + 1;
// 小数点以下を切り捨て
saikoro = Math.floor(saikoro);
です。
- Math.random()は0から0.999...(1未満)までの任意の値をランダムに返す乱数を生成するメソッドで、
- それが返す数を6倍すると、0から5.999...の値になり、
- それに1を足すから1.0から6.999...になり、
- Math.floor()メソッドで小数点以下をバッサリ切り捨てて整数部しか残らない
ので、変数saikoroは1から6までの整数のいずれかが格納されます。
JavaScriptで偶数・奇数を判定するには?
ある数が偶数か奇数かを判別するには、ある数を2で割った「余り」が0か1で判別します。
3を2で割った余りは1なので奇数、4を2で割った余りは0なので偶数。1を2で割ると「1÷2 = 0 余り1」となり、余りは1です。0は偶数の定義である「2の倍数の整数」であるかどうかで考えると 0 = 2 × 0(2のゼロ倍)なので偶数です。
ある数を別の数で割ったときの「余り」を剰余といい、JavaScriptでは剰余の計算は「%」記号を使います。
// ある整 % 別の数 = 割った余り(剰余)
console.log(3 % 2); // ← 1を返します。
console.log(4 % 2); // ← 0を返します。
console.log(1 % 2); // ← 1を返します。
console.log(0 % 2); // ← 0を返します。
真偽値はtrueかfalseのどちらかしかとらない
JavaScriptには「数値でもなく文字列でもない」真偽値というのがあり、それは必ずtrueかfalseのどちらかになるデータのことです。
「2は偶数である」は客観的に正しいですよね。これはJavaScriptでは「true:真(しん)」です。
「2は奇数である」は客観的に正しくないので「false:偽(ぎ)」です。
先ほどの剰余のコードをtrue, falseを返すようにするには以下のように書き換えます。
// 割った余り(剰余)が0であるかどうか
console.log(3 % 2 === 0); // false
console.log(4 % 2 === 0); // true
console.log(1 % 2 === 0); // false
console.log(0 % 2 === 0); // true
===は「左辺と右辺が等しい」というJavaScriptの記号です。
左辺 === 右辺
3 % 2 === 0
とすることで、3を2で割った余りが0と等しいかどうかの真偽値(この場合はfalse)を返すようになります。
ちなみに、真偽値を英語ではboolean valueといいます。true false valueではないんですね。調べたらbooleanの語源は、論理学の基礎を築いたジョージ・ブール(George Boole)に敬意を表して名付けられたものだそうです。booleanは「ブーリアン」と読みます。
比較演算子
「〇〇と〇〇は等しい」とか「〇〇は〇〇より大きい」など、比較に使われる記号のことを「比較演算子」といいます。
以下の表は比較演算子の書き方と意味のリストです。
比較演算子 | 例 | 意味 |
=== | A === B | AとBは等しい |
!== | A !== B | AとBは等しくない |
< | A < B | AはBより小さい |
> | A > B | AはBより大きい |
<= | A <= B | AはB以下 |
>= | A >= B | AはB以上 |
数学で「AとBは等しい」は「A=B」と書きますが、JavaScriptでは「=」ひとつはすでに変数への代入に使ってしまっているので、それでイコールを3つ使って「A===B」になっています。
実は、JavaScriptでは「AとBが等しい」を表すために、イコールを2つ使って「A == B」と書くことができます。しかし、この書き方では、0とfalseが等しいと判定されるなど、予期せぬ挙動やバグが発生しやすいです。なのであえてリストから除外しました。
console.log(false == '0'); // trueになる。
console.log(false === '0'); // falseになる。
詳細については、今の入門編のこの学習段階では解説が難しいので、「変数の宣言にはvar
を使わない方が良いのと同様に、==
も使わない方が無難です。」ということで。
if文を使った条件分岐処理
条件分岐のための前置きがだいぶ長くなってしまいましたが、ここからは冒頭の学習用コードをみながら条件分岐について解説していきます。
index.htmlをブラウザで開いてJavaScriptを実行して、それをコンソールで確認すると以下のようになります。(※ブラウザで開く方法は第1章のhtmlファイルをブラウザで開く方法で、コンソールは第3章のブラウザのコンソールを開く方法で触れています)
ブラウザを再読み込み(リロード)するたびにサイコロの目がランダムに変わり、サイコロの目によって異なる処理がされています。こういうのが条件分岐です。
条件分岐するひとつの方法はif文を使うことです。文法はこうなります。
if (条件式) 条件式がtrueの時に実行されるコード;
学習用コードindex.jsのこの部分です。
// 条件式が常にtrueになるのでこのconsole.log()は毎回実行される。
if (saikoro > 0) console.log("サイコロを振ると" + saikoro + "の目が出ました。");
「saikoro > 0」が条件式に該当し、「console.log("サイコロを振ると"...)」が条件式がtrueの時に実行されるコードに該当します。
条件式のsaikoro > 0は、saikoroには1~6までの整数しか格納されないので、この条件式は常にtrueを返すから、console.log("サイコロを振ると"...)は毎回実行されます。
不等号を逆にすると条件式は常にfalseになるのでconsole.log("サイコロを振ると"...)が実行されることは一生ありません。
// 条件式が常にfalseになるのでこのconsole.log()は一生実行されない。
if (saikoro < 0) console.log("サイコロを振ると" + saikoro + "の目が出ました。");
次に学習用コードのこの部分を見ていきます。
// 2で割った余り(剰余)が0の時は偶数
if (saikoro % 2 === 0) console.log("そのサイコロの目は偶数です。");
// 2で割った余り(剰余)が1の時は奇数
if (saikoro % 2 === 1) console.log("そのサイコロの目は奇数です。");
偶数・奇数判定について学びました。このコードはsaikoroが偶数か奇数かで処理を分岐しています。
常にどちらか片方のコードしか実行されません。こういう場合、このコードはif~else文を使って書き直すことができます。それが学習用コードの次の部分です。
if (saikoro % 2 === 0) console.log("くどいようですがサイコロの目は偶数です。");
else console.log("くどいようですがそのサイコロの目は奇数です。");
私の例えのセンスには相当な改善の余地がありますが、どうかこれでご勘弁ください(汗
ifの条件式がfalseの時に実行してほしいコードを書く場所がelse(それ以外の意味)です。
if (条件式) 条件式がtrueの時に実行されるコード;
else 条件式がfalseの時に実行されるコード;
「もし(if)条件式がtrueなら〇〇を実行し、それ以外(else)の時は△△を実行する」という二択の分岐処理になります。
偶数か奇数かは2択なのでif~else文で分岐処理できますが、それが3択以上になった時はelse if文を追加します。
学習用コードの最後の部分、
if (saikoro < 3) console.log("サイコロの目が3より小さかった。");
else if (saikoro <= 5) console.log("サイコロの目が3以上5以下だった。");
else console.log("サイコロの目が6だった。");
条件分岐の流れは、
- もしsaikoroが3より小さい時
- それ以外でもしsaikoroが5以下の時
- それ以外
のように、上から順番に条件式が評価されます。
2番目のelse if文は1番目のif文の条件を否定してからたどり着いているので、実質、「3以上」と「5以下」の2つの条件がtrueかどうかとなっています。
3番目のelse文はそれまでの条件をすべて否定してたどり着くので、実質、「saikoroが6」になります。
複数行書く時はブロックで囲む
条件式がtrueの時に実行されるコードが複数行になる時は{ }で囲んでブロック(block:区画の意味)にします。
// サイコロの目の乱数を生成したい
let saikoro = Math.random() * 6 + 1;
// 小数点以下を切り捨て
saikoro = Math.floor(saikoro);
if (saikoro % 2 === 0) {
// 複数行のコードはブロックで囲む。
console.log("サイコロを振ると" + saikoro + "の目が出ました。");
console.log("そのサイコロの目は偶数です。");
} else {
console.log("サイコロを振ると" + saikoro + "の目が出ました。");
console.log("そのサイコロの目は奇数です。");
}
このコードを実行すると、このように確かに複数行が実行されています。
if文の中にif文(入れ子)
if文の中にif文を書いて分岐処理を細分化できます。
// サイコロの目の乱数を生成したい
let saikoro = Math.random() * 6 + 1;
// 小数点以下を切り捨て
saikoro = Math.floor(saikoro);
// 条件式が常にtrueになるのでこのconsole.log()は毎回実行される。
if (saikoro > 0) console.log("サイコロを振ると" + saikoro + "の目が出ました。");
if (saikoro % 2 === 0) {
console.log("サイコロの目は偶数で、");
if (saikoro <= 4) {
console.log("かつ、4以下です。");
} else {
console.log("かつ、4より大きい。");
}
} else {
console.log("サイコロの目は奇数です");
if文の入れ子の上限はなく、いくらでも入れ子にできますが、コードが読みにくくなるので極端な入れ子構造はおすすめしません。
論理演算子
先程のif文の入れ子のコードは「偶数かつ4以下」でした。この「かつ」はJavaScriptでは&&記号に置き換えできます。
if (saikoro % 2 === 0 && saikoro <= 4) {
console.log("サイコロの目は偶数で、かつ、4以下です。");
} else {
console.log("サイコロの目は6か奇数です");
}
「かつ」とか「または」を記号にしたものを「論理演算子」といいます。以下、その使い方と意味のリストです。
論理演算子 | 名称 | 例 | 意味 |
&& | AND(論理積) | A && B | AとBの両方がtrue |
|| | OR(論理和) | A || B | AまたはBのどちらかがtrue |
! | NOT(否定) | !A | Aの真偽値を反転 |
OR(論理和)の記号「||」はパイプ文字が2つです。キーボード上のこのキーの場所は日本語キーボードなら配列の右上の\キーと同居していて、
Shift+\キーの同時押しで入力できます。
サイコロの出目の偶数は2または4または6のいずれかなので、論理和を使って表現できます。
if (saikoro === 2 || saikoro === 4 || saikoro === 6) {
console.log("サイコロの目は偶数です");
}
NOT(否定)は条件式の真偽値を反転させます。条件式がtrueならfalse、falseならtrueに反転します。
なので、偶数判定の条件式をNOTで反転させると奇数の条件式になります。
// サイコロの目の乱数を生成したい
let saikoro = Math.random() * 6 + 1;
// 小数点以下を切り捨て
saikoro = Math.floor(saikoro);
// 条件式が常にtrueになるのでこのconsole.log()は毎回実行される。
if (saikoro > 0) console.log("サイコロを振ると" + saikoro + "の目が出ました。");
// NOTで反転
if (!(saikoro % 2 === 0)) {
console.log("サイコロの目は奇数です");
} else {
console.log("サイコロの目は偶数です");
}
演算子の優先順位
今、NOTで反転させた偶数の条件式、
!(saikoro % 2 === 0)
カッコ( )が必須です。
!saikoro % 2 === 0
JavaScriptの!や%や===に限らず、すべての演算子には優先順位がつけられています。
演算子の優先順位 | MDNのページ下部にすべての演算子の優先順位の一覧表が掲載されています。
それによると、
- NOT記号の「!」の優先順位は15
- 剰余の「%」の優先順位は13
- 等価演算子の「===」の優先順位は9
なので優先順位が高い!saikoroが一番最初に評価されてしまいます。1~6の数値しか格納されないsaikoro変数の真偽値を反転って明らかに変ですよね。
カッコ( )の優先順位は最優先の19になっているので、カッコ( )で偶数の条件式全体を囲むことで、先に偶数判定してからNOTで真偽値を反転させるという期待した動作にすることができます。
今回までの講座で登場した演算子の優先順位表です。
演算子 | 種類 | 優先順位 |
() | グループ | 19 |
! | NOT | 15 |
* | 乗算 | 13 |
/ | 除算 | 13 |
+ | 加算 | 12 |
- | 減算 | 12 |
< | 小なり | 10 |
<= | 以上 | 10 |
> | 大なり | 10 |
>= | 以下 | 10 |
=== | 等価 | 9 |
!== | 不等価 | 9 |
&& | AND | 5 |
|| | OR | 4 |
= | 代入 | 2 |
この講座の記事を書くからこうやって調べて表にしましたが、私は演算子の優先順位なんて覚えていません。
じゃあ、どうやってるかといいますと、VSCodeで、条件式内で先に評価してほしいけど優先順位的に不安な場所を、徹底的にカッコ( )で囲んで書いて、保存時に自動で走るコード整形機能で余分なカッコを削除してもらっています。
簡単な例をあげると、1 + 2 * 3 < 8 の条件式、
if (1 + 2 * 3 < 8) {
//
}
が、2 * 3 を先に計算してくれるか優先順位がわからなくて不安なので、VSCodeで画像のように(2 * 3)とカッコで囲みます。もちろんこれは余分なカッコです。
Ctrl + Sで保存すると同時にコード整形が実行され、余分な括弧があれば削除してくれます。
試しに、掛け算より足し算を優先したいという必須のカッコ( )の場合はそのままにしてくれます。
プログラミングのプロの方で普通のテキストエディタでコードを書いている人が結構いらっしゃるのを知っていますが、少なくとも初学者のうちはVSCodeのようなコード支援機能のあるコードエディターをおすすめします。
switch~case文を使った条件分岐処理
JavaScriptでは条件分岐をif文の他にswitch~case文で書くことも出来ます。switch(スイッチ)は「切り替える」、caseは「場合」という意味なので、「〇〇が△△の場合に切り替える」という意味になります。
if文と全く同じ挙動になるようにswitch文で書いたもの(等価コードという)が以下のコードです。
let fruit = "apple";
// if文
if (fruit === "apple") {
// fruitがappleの場合
console.log("アップル");
} else if (fruit === "banana") {
// fruitがbananaの場合
console.log("バナナ");
} else {
// 上記以外の場合
console.log("アップル・バナナ以外");
}
// switch文
switch (fruit) {
case "apple":
// fruitがappleの場合
console.log("アップル");
break;
case "banana":
// fruitがbananaの場合
console.log("バナナ");
break;
default:
// 上記以外の場合
console.log("アップル・バナナ以外");
}
実行すると、
等価コードなので当たり前ですが同じ結果になっています。
switch~case文の文法は、
switch (変数) {
case "変数の値":
処理
break;
case "変数の値":
処理
break;
default:
上記のいずれにも該当しなかった場合の処理。
if文のelseの役割。
}
各caseの行末をコロン「:」で区切り、そのcaseでの処理を書いたら最後にbreakを書きます。breakによって次のcaseを飛び越えて処理はswitch文の外に出ます。
もしbreakを書き忘れると、
let fruit = "apple";
switch (fruit) {
case "apple":
console.log("アップル");
case "banana":
console.log("バナナ");
default:
console.log("アップル・バナナ以外");
}
すべてが実行されます。
switch文は x < 10 のような比較演算子を使った「範囲」での条件分岐ができません。switch文は apple や banana のような特定の値しか条件にできないため、if 文と比べると使うシーンが少ない傾向にあります。
三項演算子
簡単な条件分岐をシンプルに書くことができる三項演算子というのがあります。
以下のコードは全く同じ挙動になるif else文と三項演算子の等価コードです。
let number = 15;
let result;
// 普通のif else文
if (number >= 10) {
result = "10以上";
} else {
result = "10より小さい";
}
// 三項演算子で書くと
result = number >= 10 ? "10以上" : "10より小さい";
このコードの、
number >= 10 ? "10以上" : "10より小さい";
の部分を三項演算子といいます。文法としては、
条件式 ? trueの場合に返す値 : falseの場合に返す値
三項演算子は、3つの「項目」を使って条件に応じた結果を返します。
- 条件式(最初の項目): 何を判断するかを示す部分です。例えば、「数字が偶数かどうか」など。
- trueの場合の値(2つ目の項目): 条件がtrue(真)の場合に返される値です。
- falseの場合の値(3つ目の項目): 条件がfalse(偽)の場合に返される値です。
三項演算子は簡潔で短いコードが書けるので単純な条件分岐に適しています。
今回学んだことをクイズゲームで確認しよう!
このページで解説したことを全問のクイズ形式のゲームにしました。
ゲーム感覚で復習すると記憶に定着する助けになります。
下の「クイズを開始」ボタンでゲームを開始すると「YES」「NO」ボタンが現れますので、上から降ってくる問題が正しければ「YES」を、間違っているなら「NO」ボタンを押してください。
まとめ
JavaScriptのif文を使った条件分岐について解説しました。真偽値の概念、条件分岐の条件式に使われる比較演算子と論理演算子、それら演算子の優先順位について基本的なことを解説しました。