順番に読み進めながら学べます

真偽値と比較 — == と === の違い

JavaScript の比較を基礎から学びます。=== と == の違い、比較演算子と論理演算子の組み立て方、if が false と見なす falsy 6 種、|| による既定値までを扱います。

送料無料の条件を満たしているか、ログイン済みか、在庫が残っているか。画面の表示を切り替える処理は、いつも「その条件が成り立つかどうか」の判定から始まります。

この記事では、値が等しいかを調べる ===== の違い、条件を組み立てる比較演算子と論理演算子、そして JavaScript が「成り立たない」と見なす falsy(条件に置いたとき false と同じ扱いになる値)の 6 種類を扱います。

等しいかを調べる — === と == の違い

入力欄に打ち込まれた値と、システムが保存している値を突き合わせる場面を考えます。見た目が同じ 0 でも、入力欄から受け取ったものは文字列の "0"、保存されているものは数値の 0 です。

この 2 つを「等しい」と見なすかどうかで、JavaScript には 2 種類の演算子があります。

===型と値の両方が同じときだけ true を返します。型が違えばその時点で false です。

もう一方の == は、型が違うときに片方を変換して型をそろえてから値を比べます。"0"0=== では false== では true です。等しくないことを調べる側も !==!= の 2 種類があります。

=== と == で判定の手順が違う
"0" === 0型が違うのでそこで終わりfalse"0" == 0型をそろえてから値を比べるtrue0 === 0型も値も同じtrue
===型が違えばその場で false==型をそろえてから値を比べます。

ここでいう変換とは、"0" という文字を数値の 0 として読み替えることです。問題は、== が比べる前にこの変換を挟むことです。

変換された結果どうしを比べるので、書いた値のとおりに判定されません。空文字列 ""0 のように、見た目が違う値どうしが true になることもあります。

どの型がどちらに変換されるかは組み合わせごとに決まっていますが、その規則を覚えて読み解くより、=== を使って変換そのものを起こさないほうが結果を追いやすくなります。新しく書くコードでは ===!== を使い、型が違う値は比べる前にそろえます。変換の向きと、型をそろえる書き方は、次の型変換の記事で扱います。

== は比べる前に変換を挟む
"" == 0変換が挟まるtrue"0" == 0変換が挟まるtrue"" === 0変換しないfalse
== は変換した結果どうしを比べるので、書いた値のとおりには判定されません=== なら変換が起きません。変換の向きは次の記事で扱います。
const typedQuantity = "3";   // 入力欄に打ち込まれた数量 (文字列)
const savedQuantity = 3;     // 保存されている数量 (数値)

console.log(typedQuantity === savedQuantity);  // false  型が違う
console.log(typedQuantity == savedQuantity);   // true   型をそろえてから比べる

// 同じ型どうしなら === でも素直に判定できる
console.log(savedQuantity === 3);   // true
console.log(savedQuantity !== 3);   // false  === の否定

console.log("" == 0);         // true   空文字列も 0 に変換される
console.log("100" === 100);   // false  === なら変換されない

入力欄に打ち込まれた在庫数と、システムが持つ在庫数を突き合わせます。文字列の typedStock と数値の storedStock は宣言済みです。

① 2 つを == で比べた結果を表示してください。

② 同じ 2 つを === で比べた結果を表示してください。

③ 同じ 2 つが「型も含めて等しくない」かどうかを調べて表示してください。

(正しく実行できれば解説が表示されます)

JavaScript / TypeScript エディタ

コードを実行してください

条件を組み立てる — 比較演算子と論理演算子

実際の判定は「等しいか」だけでは足りません。合計が 5000 円以上か、ログイン済みでなおかつ管理者か、といった条件を組み立てる必要があります。

大小を調べるのが比較演算子(2 つの値の関係を調べる記号。この記事の前の節で扱った === もこの仲間です)、複数の条件をつなぐのが論理演算子(真偽値どうしを組み合わせる記号)です。

比較演算子は > < >= <= の 4 つで、結果は必ず truefalse です。

論理演算子は 3 つあります。&&両方が true のときだけ true||どちらかが true なら true!truefalse を入れ替えます。

3 つの論理演算子
&&両方が true のときだけtrue||どちらかが trueならtrue!true と false を入れ替える反対の値
&& は条件を狭め、|| は条件を広げ、! は結果を反転させます。

組み立てた条件は、if 文(丸括弧の条件が true のときだけ、続く波括弧の中を実行する構文)に渡します。条件が false のときに実行したい処理は else のあとの波括弧に書きます。

ここでは条件の結果を確かめるために使うだけで、else if を重ねる書き方や switch による分岐は、文法カテゴリの条件分岐の記事で扱います。

const cartTotal = 4800;    // カートの合計金額
const hasCoupon = true;    // クーポンを持っているか
const isMember = false;    // 会員か

console.log(cartTotal >= 5000);   // false  5000 円に届いていない
console.log(cartTotal < 5000);    // true

console.log(hasCoupon && isMember);   // false  会員ではない
console.log(hasCoupon || isMember);   // true   クーポンは持っている
console.log(!isMember);               // true   false を反転

if (cartTotal >= 5000) {
  console.log("送料無料");   // 条件が true のときだけ実行される
} else {
  console.log(`あと ${5000 - cartTotal} 円で送料無料`);   // false のときはこちら
}

ログイン状態と管理者フラグの組み合わせで、画面に出すメニューを切り替えます。ログイン済みかを表す isLoggedIn と、管理者かを表す isAdmin は宣言済みです。

① ログイン済みかつ管理者であるかを判定した結果を表示してください。

② ログイン済みで、なおかつ管理者ではないかを判定した結果を表示してください。

③ ② の条件が成り立つときだけ「マイページ」と表示してください。

JavaScript / TypeScript エディタ

コードを実行してください

truthy と falsy — if が false と見なす値

if の丸括弧には、true / false 以外の値も書けます。そのとき JavaScript は、渡された値を真偽どちらかに読み替えます。

false と読み替えられる値を falsy、それ以外を truthy(条件に置いたとき true と同じ扱いになる値)と呼びます。条件式で出会う falsy は 6 つなので、この 6 つを覚えれば残りはすべて truthy として扱えます。

6 つは false、数値の 0、空文字列 ""null(値が無いことを意図的に表す値)、undefined(値がまだ入っていないことを表す値)、そして NaN です。nullundefined の使い分けは、あとの記事であらためて扱います。

実際に書いていて出会うのは主に 0"" の 2 つなので、まずこの 2 つを覚えておけば足ります。なお NaN だけは === で自分自身と比べても false を返すので、NaN かどうかの判定には専用の書き方を使います。

falsy な 6 つの値
false0""空文字列nullundefinedNaN"0"文字列のゼロ" "空白 1 文字-10 以外の数値falsy な 6 つfalsy に見えるが truthy
上の 2 行が falsy の全部です。これ以外はすべて truthy で、下の行のように中身が 0 や空に見える値も含まれます。

つまずきやすいのが数値の 0 と空文字列です。

レビュー件数が 0 件、検索欄が未入力で "" のとき、その値をそのまま if に渡すと条件が成り立ちません。「値が入っているか」を確かめたつもりが、「値が 0 や空でないか」を確かめる処理になってしまいます。

const reviewCount = 0;    // レビュー件数
const searchWord = "";    // 検索欄に入力された文字列

if (reviewCount) {
  console.log("レビューあり");
}
if (searchWord) {
  console.log("検索語あり");
}
// 0 と空文字列は falsy なので、上の 2 つはどちらも実行されない

if (reviewCount === 0) {
  console.log("レビューはまだありません");   // これは実行される
}

0 を意味のある値として扱うときは条件を書きます

在庫数・件数・金額のように 0 そのものが意味を持つ値では、if (stock) と書くと 0 のときだけ処理が飛ばされます。stock > 0stock === 0 のように、何を確かめたいのかを条件式に書くと、読み手にも意図が伝わります。

在庫数を画面に出す処理を書きます。在庫切れの mugStock と、在庫のある bottleStock は宣言済みです。

① mugStock をそのまま条件にして、「マグカップ: 残り 5 点」のように在庫数を埋め込んだ行を表示する処理を書いてください。何が起きるかを確かめる手順なので、この行は表示されないのが正解です。

② bottleStock を同じ書き方で条件にして、同じ形で在庫数を表示してください。

③ mugStock が 0 より大きいかどうかで分けて、在庫があれば「マグカップ: 残り ○ 点」、無ければ「マグカップ: 在庫切れ」と表示してください。

JavaScript / TypeScript エディタ

コードを実行してください

短絡評価 — || で既定値を用意する

表示名が未入力のまま登録されたユーザーにも、画面には何かを出さなければなりません。こうした「値が無ければ既定値を使う」処理は、|| を使うと 1 行で書けます。

この書き方が成り立つのは、&&||真偽値を作っているのではなく、左右のどちらかの値をそのまま返しているからです。truefalse どうしを組み合わせたときは結果も truefalse になるので、ここまでの説明と食い違いません。

|| は左の値が truthy ならその左の値を返し、右側は評価すらしません。左が falsy のときだけ右の値を返します。

&& は逆で、左が falsy ならその左の値を返し、右を評価しません。この「必要になるまで右を見ない」動きを短絡評価(左側だけで結果が決まるときに右側を評価しない仕組み)と呼びます。

|| が返すのは真偽値ではなく値
"" || "ゲスト"左が falsy→ 右を返す"ゲスト""佐藤" || "ゲスト"左が truthy→ 左を返す"佐藤"0 || 1000 も falsy→ 右を返す100
左が truthy ならそのまま左を返し、falsy のときだけ右を返します。0 も falsy なので右に置き換わります
const nickname = "";   // 未入力のままのニックネーム

// || は左が falsy のときだけ右を返す
console.log(nickname || "名無しさん");    // 名無しさん
console.log("たなか" || "名無しさん");     // たなか  右は評価されない

// && は左が falsy ならその値を返し、右を評価しない
console.log(0 && "在庫あり");   // 0
console.log(5 && "在庫あり");   // 在庫あり

0 や空文字列を残したいときは || では足りません

|| は falsy な値をすべて既定値に置き換えるので、保有ポイント 0 や入力された "0" のような、意味のある falsy まで消えます。値が nullundefined のときだけ既定値を使うには ?? という別の演算子を使います。第 9 回で扱います。

表示名と保有ポイントに既定値を当てます。未入力の guestName、入力済みの memberName、保有ポイント memberPoint は宣言済みです。

① guestName が未入力のときは「ゲスト」になるようにして、表示名を表示してください。

② memberName に同じ書き方を当てた表示名を表示してください。

③ memberPoint に同じ書き方で 100 を既定値として当てた結果を表示してください。

JavaScript / TypeScript エディタ

コードを実行してください
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1console.log("0" === 0); の表示はどれですか?

Q2次のうち、falsy ではない値はどれですか?

Q3console.log(0 || 100); の表示はどれですか?