条件を組み合わせる

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部

このレッスンで分かること

  • 条件が入れ子になると読みにくくなり、抜け漏れも起きやすくなります
  • &&|| を使うと、入れ子をフラットな else if の並びに書き換えられます
  • 入れ子とフラット、どちらが読みやすいかは条件の性質で決まります

条件を組み合わせる とは

公開状態とカテゴリという 2 つの情報から、作品に付けるラベルを決める関数を書きます。入れ子を論理演算子でフラットにする書き換えが主役です。

2 つの情報で判定する

山田 太郎さんのプロフィールサイトの作品データは、次の形をしていました。

const work = { title: "プロフィールサイト", year: 2026, views: 120, published: true };

一覧画面に出すラベルを、公開状態とカテゴリの 2 つから決めたいとします。仕様は次のとおりです。

公開状態カテゴリラベル
公開"web""注目作品"
公開"web" 以外"公開中"
非公開どれでも"下書き"

判定に使う値が 2 つになりました。ここからが今回のテーマです。同じ仕様でも、書き方は何通りもあります。

まず入れ子で書いてみる

素直に考えると、まず公開状態を見て、公開ならさらにカテゴリを見る、という順になります。if の中に if を書く、いわゆる入れ子 (ネスト) の形です。

function pickupLabel(published, category) { if (published) { if (category === "web") { return "注目作品"; } else { return "公開中"; } } else { return "下書き"; } }

正しく動きます。仕様の考え方の順序がそのままコードの形になっているので、書いた本人には読みやすく感じるはずです。

問題は、条件が増えたときです。ここに「閲覧数が 100 以上なら人気作品」という条件を足し、さらに「今年の作品なら新着」を足していくと、次のような形に育ちます。

function pickupLabel(published, category, views, year) { if (published) { if (category === "web") { if (views >= 100) { if (year === 2026) { return "新着の人気 Web 作品"; } else { return "人気 Web 作品"; } } else { return "注目作品"; } } else { return "公開中"; } } else { return "下書き"; } }

インデントが右へ右へと伸びていきます。この形にはいくつも欠点があります。

  • どの else がどの if に対応しているのか、目で追わないと分からない
  • 条件の組み合わせのうち、どれが抜けているのか見つけにくい
  • 1 つ条件を足すたびにインデントが 1 段深くなる
  • 画面の右端をはみ出して、横スクロールが必要になる

深いネストは「読み手の頭の中に、いま成立している条件を全部覚えさせる」構造です。3 段目にいるとき、読み手は「公開されていて、web で、閲覧数が 100 以上」という 3 つを同時に覚えていなければなりません。人間の短期記憶はそんなに強くありません。

論理演算子でフラットにする

第 3 章で学んだ &&|| を使うと、入れ子をやめて 1 段の else if の並びに書き換えられます。&& は「かつ」、|| は「または」でした。

function pickupLabel(published, category) { if (published && category === "web") { return "注目作品"; } else if (published) { return "公開中"; } else { return "下書き"; } }

インデントが 1 段に収まりました。ビフォーアフターを並べて比べてみます。

観点入れ子フラット
インデントの深さ3 段1 段
条件と結果の対応離れていて追いにくい1 行で対になっている
枝の数の確認else を数える必要がある上から数えるだけ
条件を足すとき深くなる行が増えるだけ

フラットな形のうれしいところは、上から 1 行ずつ読めば、条件と戻り値が対になって並んでいることです。「公開かつ web なら注目作品」「公開なら公開中」「それ以外は下書き」と、日本語の仕様書をそのまま読んでいる感覚に近づきます。

2 番目の枝の else if (published) に「かつ web ではない」を書き足す必要はありません。else if は前の条件が false だったときにしか来ないからです。前のレッスンで見た性質が、ここでも効いています。

書き換えるときは、条件の順番が変わっていないかを必ず確かめてください。入れ子の内側にあった条件は、フラットにすると外側の条件と && でつながって、より狭い条件になります。狭い条件が先、広い条件が後、という並びが崩れると、前のレッスンで見たデッドコードが生まれます。

入れ子のままがよい場合もある

いつでもフラットが正解というわけではありません。次のような場合は入れ子のほうが素直です。

  • 外側の条件が「そもそも処理する対象か」を決めていて、内側の分岐と性質が違う
  • 内側の分岐が 5 つも 6 つもあり、&& でつなぐと同じ条件を何度も書くことになる
  • 外側の条件が長い式で、繰り返し書くと 1 行が読めない長さになる

判断の目安は「同じ条件を 3 回以上書くことになるならフラットにしない」です。また、条件式そのものに名前を付けて短くする手もあります。

function pickupLabel(published, category) { const isFeatured = published && category === "web"; if (isFeatured) { return "注目作品"; } else if (published) { return "公開中"; } else { return "下書き"; } }

isFeatured という名前が付いたことで、if の行を読むだけで意図が分かるようになりました。条件式が長くなってきたら、変数に切り出すことを検討してください。真偽値の変数名は ishascan で始めるのが慣習です。

ネストを浅くするもう 1 つの定番として、関数の先頭で対象外の値をはじいてしまう書き方があります。これは第 6 章の関数のレッスンで扱います。ここでは論理演算子による書き換えに集中してください。

よくある間違い

  • &&|| を取り違える — 「公開されていて、かつ web」は && です。|| にすると、非公開の web 作品まで注目作品になってしまいます。
// NG。published が false でも category が web なら通ってしまう if (published || category === "web") { // OK if (published && category === "web") {
  • 比較を省略して書く — 数学の書き方をそのまま持ち込むと、意図しない結果になります。
// NG。category === "web" || "frontend" は常に truthy if (category === "web" || "frontend") { // OK if (category === "web" || category === "frontend") {

"frontend" という文字列は空文字ではないので、それだけで true 扱いになります。|| の左が false でも右が true になるため、この条件はどんなカテゴリでも成立してしまいます。比較演算子は省略できません。

  • フラットにしたのに順番を直さない — 入れ子を機械的に開いただけで、広い条件を先に書いてしまうパターンです。書き換えたら、必ず代表的な入力を 3 つほど手で流して、元のコードと同じ答えになるか確かめてください。今回なら公開かつ web、公開かつ design、非公開の 3 つで足ります。

要件

  1. 関数名は pickupLabel、引数は真偽値 published とカテゴリ名の文字列 category の 2 つ
  2. published が true かつ category が "web" なら "注目作品" を返す
  3. published が true でカテゴリが "web" 以外なら "公開中"、published が false なら "下書き" を返す
  4. if の入れ子ではなく && を使い、インデント 1 段の else if の並びで書く

入出力例

pickupLabel(true, "web")"注目作品" pickupLabel(true, "design")"公開中" pickupLabel(false, "web")"下書き" pickupLabel(false, "design")"下書き" pickupLabel(true, "")"公開中"

ヒント

main.js
main.js
学習モード

メモ

条件を組み合わせる

⌘S で保存