1.`if`と`else` — 分かれ道を作る
第1講で、コードは上から下へ順に実行されると述べました。条件分岐は、この流れに分かれ道を作ります。if (条件) { … }と書くと、かっこの中の条件が真のときだけ波かっこの中のコードを実行し、偽なら飛ばします。条件が偽のときに別にやることがあれば、その後ろにelse { … }を付けます。二つの道のうち、ちょうど片方だけが実行されます。
条件の場所には、結果がtrueかfalseになる式を書きます。第2講の真偽値がここで使われます。age >= 19は、ageが19以上ならtrue、そうでなければfalseになる式です。条件式を先にconsole.logで出力してみれば、条件分岐がどちらに進むかを前もって知ることができ、条件分岐が思いどおりに動かないときに原因を探す助けになります。
波かっこの中のコードは2文字分字下げして、「このコードはこの条件に属している」ことが目で見えるようにします。実行環境は字下げを見ずに波かっこで区切りますが、人は字下げで構造を読みます。字下げがずれたコードは読む人をだますことがあるので、いつもそろえておきます。波かっこの中のコードが1行だけでも、波かっこを省略しないほうが、あとで行を足すときのミスが減ります。
const age = 17;
console.log(age >= 19);
if (age >= 19) {
console.log("一般料金");
} else {
console.log("学生料金");
}false 学生料金
2.`else if` — 複数の道は上から順に
道が三つ以上あるときは、else ifをつなげます。実行環境は上から条件を一つずつ調べ、最初に真になった道一つだけを実行して、残りはすべて飛ばします。どの条件も真でなければ、最後のelseが実行されます。ですからelseは、「上のどのケースでもない残りすべて」を受け持つ場所です。
「最初に真になったもの一つだけ」という規則があるので、条件の順番が大切です。点数で評価を付けるなら、高い基準から順に調べる必要があります。95点はscore >= 90も真でscore >= 80も真ですが、80の条件を先に書くと、95点がBになってしまいます。高い基準から下りていけば、後の条件では「前の条件はすでに偽だった」ことを前提にできるので、score >= 80 && score < 90のように範囲を両側から書く必要もなくなります。
条件分岐を書く前に表に整理してみると、抜けている区間や重なっている区間を見つけやすくなります。下の例のように「90以上A、80以上B、70以上C、残りF」と決めたなら、表に書いたとおりに上から書き写せばよいのです。評価の基準は例であり、実際の基準は学校や会社によって違います。
const score = 85;
if (score >= 90) {
console.log("A");
} else if (score >= 80) {
console.log("B");
} else if (score >= 70) {
console.log("C");
} else {
console.log("F");
}B
// 順番を間違えた例
const s = 95;
if (s >= 80) {
console.log("B");
} else if (s >= 90) {
console.log("A");
}B
3.比較演算子と`===`対`==`
二つの値を比べる演算子は、大きい(>)、小さい(<)、以上(>=)、以下(<=)、等しい(===)、等しくない(!==)です。結果はいつもtrueかfalseです。等しいかどうかを比べるときに=を一つだけ書くと、比較ではなく値を入れる代入になってしまうので注意してください。このミスはとてもよくあり、場合によってはエラーにならずにおかしな動きをします。
JavaScriptには「等しい」が二種類あります。===(厳密等価)は、データ型と値の両方が同じときだけtrueです。==(緩い等価)は、データ型が違うと第2講で見た暗黙の型変換をしてから比べます。そのため1 == "1"はtrue、0 == ""もtrueになります。規則が複雑で予測しにくいので、ほとんどすべてのコーディングガイドやチェックツールが、===と!==だけを使うようにすすめています。このコースでも、いつも===を使います。
文字列どうしも比べられます。===は文字が一つ残らず同じでなければならないので、"ゆうき" === "ゆうき "(最後に空白)はfalseです。ユーザーの入力を比べるとき、前後の空白のせいで一致しないことがよくあるので、第7講でtrimを使って整える方法を学びます。文字列に<や>を使うと、辞書順に近い文字コードの順で比べます。"10" < "9"がtrueになるように、数に見える文字列はおかしな比べ方になるので、先に数値に変えます。
==は型変換してから比べるので、結果が予想と違ってきますconsole.log(3 > 2, 3 >= 3, 3 !== 3);
console.log(1 === "1", 1 == "1");
console.log(0 == "", 0 === "");
console.log(null == undefined, null === undefined);true true false false true true false true false
console.log("ゆうき" === "ゆうき ");
console.log("10" < "9", 10 < 9);
console.log(Number("10") < Number("9"));false true false false
| 演算子 | 意味 | 例 | 結果 |
|---|---|---|---|
=== | データ型と値の両方が等しい | 5 === 5 | true |
!== | 等しくない(厳密) | 5 !== "5" | true |
> / < | 大きい/小さい | 3 < 2 | false |
>= / <= | 以上/以下 | 60 >= 60 | true |
== | 型変換してから等しい(使わない) | 1 == "1" | true |
4.論理演算子 — かつ`&&`、または`||`、ではない`!`
複数の条件をまとめるときは、論理演算子を使います。A && BはAとBが両方とも真のときだけ真で、A || Bはどちらか一方でも真なら真です。!Aは真と偽をひっくり返します。「会員で、かつ3万ウォン以上買った」は&&、「会員であるか、または3万ウォン以上買った」は||です。日常の言葉の「と」や「か」はあいまいに使われがちなので、条件を言葉で決めたあと、どちらなのかをもう一度確かめるとよいでしょう。
&&と||は、左側だけで答えが決まれば右側を計算しません。A && BでAが偽ならBに関係なく偽なのでBを見ず、A || BでAが真ならBを見ません。これを利用してuser !== null && user.age >= 19のように書くと、userがnullのときは右側を読まないので、第2講で見たTypeErrorを避けられます。順番を入れ替えると、この守りがなくなります。
&&と||を一つの式に混ぜると、&&が先に計算されます。けれども、この優先順位を覚えて書くより、かっこでくくって意図を示すほうがずっと安全です。範囲を表すときに数学のように10 <= x <= 20と書くと、エラーにはなりませんが思いどおりには動きません。必ずx >= 10 && x <= 20のように二つの比較に分けて書きます。
const isMember = false;
const total = 32000;
console.log(isMember && total >= 30000);
console.log(isMember || total >= 30000);
console.log(!isMember);false true true
10 <= xが先にtrueになり、true <= 20は1 <= 20に変わって真になりますconst x = 25;
console.log(10 <= x <= 20); // 思いどおりにならない
console.log(x >= 10 && x <= 20);true false
5.`truthy`と`falsy` — 真偽値でない値も条件になる
ifのかっこの中に真偽値でない値を入れても、エラーにはなりません。JavaScriptはその値を真か偽に変えて判断します。偽とみなされる値(falsy)は決まっています。false、0、-0、0n、空文字列""、null、undefined、NaNです。この一覧にない値は、すべて真とみなされます(truthy)。空の配列[]や空のオブジェクト{}、文字の"0"や"false"もtruthyだという点が、よく混乱のもとになります。
この性質のおかげで、if (name) { … }のように「値が入っていれば」を短く書けます。しかし落とし穴があります。個数や金額では0は正常な値なのに、falsyなのです。在庫が0個の商品をif (stock)で調べると、「在庫の情報がない」と「在庫が0個」が同じ道に入ってしまいます。AIが書いたコードでもよく見かけるミスです。
ですから、何を確かめたいのかがはっきりしているときは、条件を具体的に書きます。値が空かどうかを見るならstock === nullやstock === undefined、0より大きいかを見るならstock > 0、空文字列かどうかを見るならname === ""のように書きます。ある値がtruthyかどうか気になるときは、Boolean(値)で直接確かめられます。
"0"と空の配列はtruthyですconsole.log(Boolean(0), Boolean(""), Boolean(null));
console.log(Boolean(NaN), Boolean(undefined));
console.log(Boolean("0"), Boolean("false"));
console.log(Boolean([]), Boolean(-1));false false false false false true true true true
const stock = 0;
if (stock) {
console.log("購入できます");
} else {
console.log("在庫情報なし?"); // 0個なのにここに来る
}
if (stock === null) {
console.log("在庫情報なし");
} else if (stock > 0) {
console.log("購入できます");
} else {
console.log("品切れ");
}在庫情報なし? 品切れ
6.境界値 — 条件分岐は境界で間違える
条件分岐のバグは、たいてい境界で生まれます。「60点以上で合格」をscore > 60と書くと、60点が不合格になります。59点と61点だけで試しても、このミスは見つかりません。ですから条件分岐を確かめるときは、境界のすぐ下、境界そのもの、境界のすぐ上の値を必ず入れてみます。これにいちばん小さな値(0)といちばん大きな値(100)、そして入ってきてはいけない値(マイナスや100超え)まで加えれば、たいていのミスが見えてきます。
規則を言葉で決める段階から、境界をはっきりさせる必要があります。「19歳以上」「3万ウォン以上で送料無料」「10個を超えたら割引」のうち、「以上」は>=、「超える」は>、「以下」は<=、「未満」は<です。要件が「3万ウォンから」のようにあいまいなら、コードを書く前に、ちょうど3万ウォンがどちらに入るのかを確かめるのが正解です。AIにコードを頼むときも、境界を言葉ではっきり書いておけば、結果がずっと正確になります。
確かめる値を表にまとめておけば、それがそのままテストケースになります。このコースの練習場の採点機がしていることも同じで、決めておいた入力を入れて期待値と比べます。第5講で関数を学べば、こうしたテストをもっとかんたんに作れるようになり、第10講では、AIが書いたコードをこの方法で検証します。
| 入力 | 選んだ理由 | 期待する結果 | `score > 60`と間違えて書くと |
|---|---|---|---|
59 | 境界のすぐ下 | 不合格 | 不合格 |
60 | 境界そのもの | 合格 | 不合格(バグ発見) |
61 | 境界のすぐ上 | 合格 | 合格 |
0 / 100 | いちばん小さい・大きい値 | 不合格/合格 | 不合格/合格 |
-5 / 120 | 入ってきてはいけない値 | 誤った点数として扱う | 不合格/合格(チェックなし) |
const orders = [[29999, false], [30000, false], [0, true]];
for (const [total, isMember] of orders) {
let fee = 3000;
if (total >= 30000 || isMember) {
fee = 0;
}
console.log(total, isMember, fee);
}29999 false 3000 30000 false 0 0 true 0
- ステップ1 境界を見つける:金額の境界は30,000ウォンで、「以上」なので
>=です。会員かどうかは真・偽の二通りです。 - ステップ2 テストの値を選ぶ:非会員で29,999ウォン・30,000ウォン、そして会員で0ウォン(ごく小さな金額でも会員なら無料になるか)を選びます。
- ステップ3 条件を書く:
total >= 30000 || isMemberが真なら0、そうでなければ3000です。 - 検算:29,999ウォンの非会員だけが3,000ウォンで、残りは0ウォンのはずです。30,000ウォンが3,000ウォンになったら、
>と書き間違えています。
for … ofは第4講で学ぶ繰り返しで、[29999, false]のように角かっこでまとめた並びは第6講で学ぶ配列です。const [total, isMember]は、その並びの1つ目と2つ目の値を順に二つの名前に入れる文法です。今は「ケースを一つずつ取り出して、同じ条件分岐に入れてみる」ということだけ見ておけば十分です。📌 要点まとめ
if・else if・elseは上から調べ、最初に真になった道一つだけを実行する — 順番が大切- 等しいかを比べるときはいつも
===・!==を使う —==は型変換してから比べるので予測しにくい &&は全部が真、||はどれか一つでも真、!は反転で、範囲はx >= 10 && x <= 20のように分けて書くfalsyなのはfalse・0・""・null・undefined・NaNなどで、0が正常な値なら条件を具体的に書く- 条件分岐は、境界のすぐ下・境界・すぐ上と両端の値、誤った値でテストする
🧪 コード実習
条件分岐で関数を完成させる練習です。採点機は、境界値を含むいろいろな入力を入れて試します。
コードはこのブラウザの中の隔離された場所でだけ実行され、サーバーには送られません。ネットワークには接続できず、2秒を超えると止まります。書き換えたコードはこのブラウザにだけ保存されます。Ctrl+Enter(⌘+Enter)で実行、Tabキーは空白2つ(Escの後のTabで次へ移動)。
JavaScriptが無効なので実行はできませんが、問題・最初のコード・自動チェックの内容・解答例はそのまま読めます。
1対象年齢かどうかを判断する
仮の規則で、19歳以上を大人として扱います。isAdult(age)は、年齢age(数値)が19以上ならtrue、そうでなければfalseを返します。
isAdult(18)期待値falseisAdult(19)期待値trueisAdult(20)期待値trueisAdult(0)期待値false
💡 ヒント
「以上」は境界を含みます。19を入れてみましょう。
解答例を見る
function isAdult(age) {
return age >= 19;
}
2点数で評価を付ける
grade(score)は0〜100点の点数を受け取り、90以上なら"A"、80以上なら"B"、70以上なら"C"、それ以外は"F"を返します。
grade(100)期待値"A"grade(90)期待値"A"grade(89)期待値"B"grade(70)期待値"C"grade(69)期待値"F"grade(0)期待値"F"
💡 ヒント
高い基準から調べます。returnに出会うと関数はすぐに終わるので、後ろの条件は見ません。
解答例を見る
function grade(score) {
if (score >= 90) {
return "A";
} else if (score >= 80) {
return "B";
} else if (score >= 70) {
return "C";
} else {
return "F";
}
}
3送料の計算
仮のネットショップの規則です。shippingFee(total, isMember)は、注文金額totalが30000以上か、会員(isMemberがtrue)なら0、そうでなければ3000を返します。ただし、注文金額が0以下(空の注文)なら、会員かどうかに関係なく0を返してください。
shippingFee(29999, false)期待値3000shippingFee(30000, false)期待値0shippingFee(5000, true)期待値0shippingFee(0, false)期待値0shippingFee(1, false)期待値3000
💡 ヒント
空の注文を先にふるい落とし、そのあとでtotal >= 30000 || isMemberを調べます。
解答例を見る
function shippingFee(total, isMember) {
if (total <= 0) {
return 0;
}
if (total >= 30000 || isMember) {
return 0;
}
return 3000;
}
4入場料と誤った入力
仮の博物館の入場料です。ticketPrice(age)は、7歳未満なら0、7歳以上19歳未満なら3000、19歳以上65歳未満なら6000、65歳以上なら0を返します。年齢がマイナスか数値でなければ(typeof age !== "number")、nullを返してください。
ticketPrice(6)期待値0ticketPrice(7)期待値3000ticketPrice(19)期待値6000ticketPrice(65)期待値0ticketPrice(-1)期待値nullticketPrice("20")期待値null
💡 ヒント
typeof age !== "number" || age < 0をいちばん前で調べれば、後ろの条件は正しい数値だけを扱えます。「未満」は<です。
解答例を見る
function ticketPrice(age) {
if (typeof age !== "number" || age < 0) {
return null;
}
if (age < 7) {
return 0;
} else if (age < 19) {
return 3000;
} else if (age < 65) {
return 6000;
}
return 0;
}
🤖 AIにはこう聞いてみましょう
コピーして [ ] の部分を自分の状況に書き換えて使います。答えはそのまま信じず、本文と比べて確かめましょう。
条件の規則をコードにする前に
次の規則をJavaScriptの条件分岐にしたいと思っています。コードを書く前に、まず境界値(以上・超える・以下・未満)があいまいなところを質問してください。そして、すべてのケースを入力・期待する結果の表にまとめてください。表の各行がテストケースになるようにしてください。規則:[規則の説明]
AIが書いた条件分岐を見直すとき
下の条件分岐について、(1) `else if`の順番のせいでたどり着けない道、(2) `==`の使用、(3) 0や空文字列を`falsy`として誤ってふるい落としている箇所、(4) 境界値が規則と違う箇所がないか、一つずつ確かめてください。それぞれの問題について、それを明らかにする入力値もあわせて教えてください。規則:[規則] コード:[コードを貼り付け]
`truthy`・`falsy`の感覚を練習したいとき
JavaScriptの`truthy`・`falsy`と`===`/`==`の比較についての予測問題を10問作ってください。各問題は`if (値)`がどちらの道に進むかを尋ねる形にし、答えは伏せておいて、私が答えたら理由と一緒に教えてください。
🧰 関連ツール
この講義で扱ったJSON・正規表現・テキストを、その場で確かめたり整えたりできるツールです。本物の個人情報やパスワードは貼り付けないでください。
- MDN Web Docs — JavaScriptガイドの制御フローとエラー処理(if...else)、式と演算子
- MDN Web Docs — Falsy・Truthy の用語解説、等価性の比較と同一性(Equality comparisons and sameness)
- ソフトウェアテスト入門書の境界値分析に関する一般的な内容
学習目標をすべて達成できたら完了を押しましょう。
このブラウザでは保存できないため、この画面でのみ表示されます。