Q1console.log("0" === 0); の表示はどれですか?
真偽値と比較 — == と === の違い
JavaScript の比較を基礎から学びます。=== と == の違い、比較演算子と論理演算子の組み立て方、if が false と見なす falsy 6 種、|| による既定値までを扱います。
送料無料の条件を満たしているか、ログイン済みか、在庫が残っているか。画面の表示を切り替える処理は、いつも「その条件が成り立つかどうか」の判定から始まります。
この記事では、値が等しいかを調べる === と == の違い、条件を組み立てる比較演算子と論理演算子、そして JavaScript が「成り立たない」と見なす falsy(条件に置いたとき false と同じ扱いになる値)の 6 種類を扱います。
等しいかを調べる — === と == の違い
入力欄に打ち込まれた値と、システムが保存している値を突き合わせる場面を考えます。見た目が同じ 0 でも、入力欄から受け取ったものは文字列の "0"、保存されているものは数値の 0 です。
この 2 つを「等しい」と見なすかどうかで、JavaScript には 2 種類の演算子があります。
=== は型と値の両方が同じときだけ true を返します。型が違えばその時点で false です。
もう一方の == は、型が違うときに片方を変換して型をそろえてから値を比べます。"0" と 0 は === では false、== では true です。等しくないことを調べる側も !== と != の 2 種類があります。
=== は型が違えばその場で false、== は型をそろえてから値を比べます。ここでいう変換とは、"0" という文字を数値の 0 として読み替えることです。問題は、== が比べる前にこの変換を挟むことです。
変換された結果どうしを比べるので、書いた値のとおりに判定されません。空文字列 "" と 0 のように、見た目が違う値どうしが true になることもあります。
どの型がどちらに変換されるかは組み合わせごとに決まっていますが、その規則を覚えて読み解くより、=== を使って変換そのものを起こさないほうが結果を追いやすくなります。新しく書くコードでは === と !== を使い、型が違う値は比べる前にそろえます。変換の向きと、型をそろえる書き方は、次の型変換の記事で扱います。
== は変換した結果どうしを比べるので、書いた値のとおりには判定されません。=== なら変換が起きません。変換の向きは次の記事で扱います。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 === なら変換されない
条件を組み立てる — 比較演算子と論理演算子
実際の判定は「等しいか」だけでは足りません。合計が 5000 円以上か、ログイン済みでなおかつ管理者か、といった条件を組み立てる必要があります。
大小を調べるのが比較演算子(2 つの値の関係を調べる記号。この記事の前の節で扱った === もこの仲間です)、複数の条件をつなぐのが論理演算子(真偽値どうしを組み合わせる記号)です。
比較演算子は > < >= <= の 4 つで、結果は必ず true か false です。
論理演算子は 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 のときはこちら
}
truthy と falsy — if が false と見なす値
if の丸括弧には、true / false 以外の値も書けます。そのとき JavaScript は、渡された値を真偽どちらかに読み替えます。
false と読み替えられる値を falsy、それ以外を truthy(条件に置いたとき true と同じ扱いになる値)と呼びます。条件式で出会う falsy は 6 つなので、この 6 つを覚えれば残りはすべて truthy として扱えます。
6 つは false、数値の 0、空文字列 ""、null(値が無いことを意図的に表す値)、undefined(値がまだ入っていないことを表す値)、そして NaN です。null と undefined の使い分けは、あとの記事であらためて扱います。
実際に書いていて出会うのは主に 0 と "" の 2 つなので、まずこの 2 つを覚えておけば足ります。なお NaN だけは === で自分自身と比べても false を返すので、NaN かどうかの判定には専用の書き方を使います。
つまずきやすいのが数値の 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 > 0 や stock === 0 のように、何を確かめたいのかを条件式に書くと、読み手にも意図が伝わります。
短絡評価 — || で既定値を用意する
表示名が未入力のまま登録されたユーザーにも、画面には何かを出さなければなりません。こうした「値が無ければ既定値を使う」処理は、|| を使うと 1 行で書けます。
この書き方が成り立つのは、&& と || が真偽値を作っているのではなく、左右のどちらかの値をそのまま返しているからです。true と false どうしを組み合わせたときは結果も true か false になるので、ここまでの説明と食い違いません。
|| は左の値が truthy ならその左の値を返し、右側は評価すらしません。左が falsy のときだけ右の値を返します。
&& は逆で、左が falsy ならその左の値を返し、右を評価しません。この「必要になるまで右を見ない」動きを短絡評価(左側だけで結果が決まるときに右側を評価しない仕組み)と呼びます。
const nickname = ""; // 未入力のままのニックネーム
// || は左が falsy のときだけ右を返す
console.log(nickname || "名無しさん"); // 名無しさん
console.log("たなか" || "名無しさん"); // たなか 右は評価されない
// && は左が falsy ならその値を返し、右を評価しない
console.log(0 && "在庫あり"); // 0
console.log(5 && "在庫あり"); // 在庫あり
0 や空文字列を残したいときは || では足りません
|| は falsy な値をすべて既定値に置き換えるので、保有ポイント 0 や入力された "0" のような、意味のある falsy まで消えます。値が null や undefined のときだけ既定値を使うには ?? という別の演算子を使います。第 9 回で扱います。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2次のうち、falsy ではない値はどれですか?
Q3console.log(0 || 100); の表示はどれですか?