1.

JavaScript の if 文|truthy と falsy・=== を使う理由

編集
この記事の要点
  • 構文は if (条件) { } / else if / else条件のかっこは省略できない
  • 比較は 必ず ===== は型を変換してから比べるため直感に反する
  • 偽になるのは false 0 -0 0n "" null undefined NaN の 8 つ。それ以外はすべて真
  • "0" "false" [] {}。空配列の判定は length === 0
  • 波かっこの省略は行を足したときに壊れる。常に付ける

基本

const score = 75;

if (score >= 80) {
  console.log("A");
} else if (score >= 60) {
  console.log("B");
} else {
  console.log("C");
}

else if はいくつでも並べられ、else は省略できます。上から順に評価され、最初に真になった枝だけが実行されます。

波かっこを省略しない

// 1 行なら省略できるが…
if (ok) console.log("OK");

// あとから行を足すと壊れる
if (ok)
  console.log("OK");
  console.log("これは条件に関係なく必ず実行される");   // ← インデントに騙される

// 常に波かっこを付ける
if (ok) {
  console.log("OK");
  console.log("こちらは条件付き");
}

真偽の判定ルール

偽(falsy)— この 8 つだけ真(truthy)— それ以外すべて
false 0 -0 0n "" null undefined NaN"0" "false" " " [] {} -1 Infinity 関数 …
if ("0") console.log("真");        // 実行される(空でない文字列)
if ([]) console.log("真");         // 実行される(空配列でも真)
if ({}) console.log("真");         // 実行される

// 空配列の判定
const items = [];
if (items.length === 0) console.log("空です");
// if (!items) は永遠に成立しない

// 空オブジェクトの判定
if (Object.keys(obj).length === 0) console.log("空です");

// 数値の 0 が有効値のとき
const count = 0;
if (count) console.log("ここには来ない");        // 0 は偽
if (count !== undefined) console.log("こちら");  // 意図どおり

[]{} が真なのは他の言語から来ると最も間違えやすい点です。「空かどうか」は必ず length やキーの数で判定してください。

== ではなく === を使う

console.log(1 == "1");        // true    型を変換してから比べる
console.log(1 === "1");       // false

console.log(0 == "");         // true
console.log(0 == false);      // true
console.log(null == 0);       // false   ← null は数値に変換されない
console.log(null == undefined); // true  ← この 2 つだけは等しい
console.log(NaN == NaN);      // false   NaN はどれとも等しくない

// NaN の判定
console.log(Number.isNaN(NaN));       // true
console.log(Number.isNaN("abc"));     // false(変換しない。こちらを使う)
console.log(isNaN("abc"));            // true (変換してしまう古い関数)

例外的に == nullnullundefined をまとめて判定する書き方として広く使われています。それ以外は === にしてください。

if (value == null) {          // null か undefined
  // ...
}
if (value === null || value === undefined) {  // 同じ意味(明示的)
}

入力値は文字列で来る

const input = document.querySelector("#age");

if (input.value === 20) { }          // 常に false("20" と 20 は別)
if (Number(input.value) === 20) { }  // 正しい

// 空欄と 0 を区別する
if (input.value === "") console.log("未入力");
if (Number(input.value) === 0) console.log("0 が入力された");

// 数値に変換できるか確かめる
const n = Number(input.value);
if (input.value.trim() === "" || Number.isNaN(n)) {
  console.log("数値を入力してください");
}

input.value dataset localStorage の値はすべて文字列です。比較の前に Number() で変換してください。

複数条件

const user = { age: 25, active: true, plan: "pro" };

if (user.age >= 20 && user.active) { }        // かつ
if (user.plan === "pro" || user.plan === "biz") { }  // または
if (!user.active) { }                          // でない

// 候補が多いなら includes
if (["pro", "biz", "ent"].includes(user.plan)) { }

// 短絡評価を安全チェックに使う
if (user && user.profile && user.profile.name) { }
if (user?.profile?.name) { }                   // オプショナルチェーン(推奨)

// 条件が長いときは名前を付ける
const isAdult = user.age >= 20;
const isPaid = ["pro", "biz"].includes(user.plan);
if (isAdult && isPaid && user.active) { }

// 連鎖比較は書けない
if (0 < user.age < 10) { }                    // 常に true になる(誤り)
if (0 < user.age && user.age < 10) { }        // 正しい

0 < age < 10(0 < age)true になり、true < 101 < 10 として評価されるため常に真になります。エラーにならないぶん厄介です。

三項演算子と ?? の使い分け

const label = score >= 60 ? "合格" : "不合格";

// || は falsy すべてを弾くので 0 や "" が消える
const count1 = input || 10;      // input が 0 でも 10 になる
const count2 = input ?? 10;      // input が null / undefined のときだけ 10

// ?? と || は混ぜて書けない(かっこが必要)
// const x = a ?? b || c;        // SyntaxError
const x = (a ?? b) || c;

ネストを浅くする

// ネストが深い
function price(user) {
  if (user) {
    if (user.active) {
      if (user.vip) return 800;
      return 1000;
    }
  }
  return 0;
}

// 早期 return で平らにする
function price(user) {
  if (!user?.active) return 0;
  return user.vip ? 800 : 1000;
}

// 値を比べるだけの分岐はオブジェクトに置き換えられる
const LABELS = { start: "開始", stop: "停止" };
const label = LABELS[command] ?? "不明";

else if が 5 個以上続いて値を比べているだけなら、オブジェクトの引き当てか switch に置き換えると見通しが良くなります(switch)。

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. if文
  2. switch

最近更新/作成されたページ