条件を組み合わせる
このレッスンで分かること
- 判定材料が 2 つ以上あると、
ifの入れ子はどんどん深くなります&&と||を使えば、入れ子をインデント 1 段の並びに書き換えられます
インデントが右へ逃げていく
判定に使う値が 2 つになった瞬間、コードの形が変わります。作品カードに出す一言を、本人が見ているかどうかと閲覧数の 2 つから決めるとしましょう。素直に考えると、まず本人かどうかを見て、本人ならさらに閲覧数を見る、という順になります。
JavaScript
function cardNote(isOwner, views) {
if (isOwner) {
if (views >= 100) {
return "よく見られています";
} else {
return "これから伸ばしましょう";
}
} else {
return "作品を見る";
}
}正しく動きますし、考えた順序がそのまま形になっているので、書いた本人には読みやすく感じます。問題は条件が増えたときです。ここに「今年の作品なら新着」を足し、さらに「画像付きなら見出しを変える」を足すと、if が 4 段重なり、インデントが画面の右端へ逃げていきます。そうなると、次のことが起きます。
- どの
elseがどのifの相方なのか、目で追わないと分からない - 条件の組み合わせのうち、どれが抜けているのか見つけられない
- 1 つ足すたびに全体が 1 段深くなる
深い入れ子は、読み手に「いま成立している条件」を全部覚えさせる構造です。3 段目にいる読み手は「本人で、100 以上で、今年の作品」の 3 つを同時に頭に置いておかなければなりません。人間の短期記憶はそこまで強くありません。
&& でつなぐと 1 段に戻る
&& は「かつ」でした。内側の条件を外側の条件と && でつなげば、入れ子をやめて 1 段の並びに書き換えられます。
JavaScript
function cardNote(isOwner, views) {
if (isOwner && views >= 100) {
return "よく見られています";
} else if (isOwner) {
return "これから伸ばしましょう";
} else {
return "作品を見る";
}
}| 観点 | 入れ子 | 1 段の並び |
|---|---|---|
| インデント | 3 段 | 1 段 |
| 条件と戻り値 | 離れていて追いにくい | 1 行で対になっている |
| 条件を足すとき | 深くなる | 行が増えるだけ |
うれしいのは、上から 1 行ずつ読むだけで条件と戻り値が対になって並ぶことです。日本語の仕様書をそのまま読んでいる感覚に近づきます。2 つ目の枝に「かつ 100 未満」を書き足す必要が無いのは、前のレッスンで見たとおりです。
条件式が長くなってきたら、真偽値の変数に切り出す手もあります。const isPopular = isOwner && views >= 100; としておけば、if の行を読むだけで意図が伝わります。真偽値の変数名は is や has で始めるのが慣習です。
よくある間違い
&&と||を取り違える — 「本人で、かつ 100 以上」は&&です。||にすると、本人でない人にまで同じ一言が出てしまいます- 比較を省略して書く — 数学の書き方をそのまま持ち込むと、条件がいつも成立します
JavaScript
// NG。"png" は空文字ではないので、それだけで true 扱いになる
if (ext === "jpg" || "png") { }
// OK
if (ext === "jpg" || ext === "png") { }- 書き換えたのに順番を直さない — 入れ子を機械的に開くと、広い条件が先に来てしまうことがあります。書き換えたら代表的な入力を 3 つほど手で流し、元のコードと同じ答えになるか確かめてください
要件
- 関数名は pickupLabel、引数は真偽値 published とカテゴリ名の文字列 category の 2 つ
- published が true かつ category が "web" なら "注目作品" を返す
- published が true でカテゴリが "web" 以外なら "公開中"、published が false なら "下書き" を返す
- if の入れ子ではなく && を使い、インデント 1 段の else if の並びで書く
入出力例
pickupLabel(true, "web") → "注目作品"
pickupLabel(true, "design") → "公開中"
pickupLabel(false, "web") → "下書き"
pickupLabel(false, "design") → "下書き"
pickupLabel(true, "") → "公開中"ヒント
編集 ゆめさく編集部