こんにちは!フロントエンドの現場を渡り歩いているチーフアーキテクトの私です。
JavaScriptを触り始めてすぐの頃って、「あれ?思った通りに動かないぞ…」という壁にぶつかりがちですよね。特に、値が「無い」ときや「ゼロ」のときの扱いで、夜も眠れなくなるほど悩んだ経験、ありませんか?(私はあります、遠い目……)。
今回は、そんなJavaScriptの「あるあるな罠」をスッキリ解消してくれる「Null合体演算子(`??`)」と、おなじみの「論理和(`||`)」の違いについて、お買い物のレジでの出来事に例えながら、優しく紐解いていきたいと思います。
大丈夫、ひとつずつ見ていけば絶対に理解できますから、肩の力を抜いてコーヒーでも飲みながら読んでいってくださいね。
—
現場でよくある「あれ?」の正体
JavaScriptを書いていると、「もし、この変数にデータが入っていなかったら、代わりに『未設定』という文字を表示したいな」という場面に出くわします。
そんなとき、先輩から「論理和(`||`)を使うんだよ」と教わったり、モダンなコードで「Null合体演算子(`??`)」を見かけたりするはずです。
パッと見は似ているこの2人ですが、実は「何を『無いもの(ダメなもの)』とみなすか」の基準がまったく違うんです。ここを勘違いしていると、作ったWebサイトで「0個のアイテムが勝手に消える」といった怪奇現象(バグ)に悩まされることになります。
一体どういうことなのか、身近な例えで見てみましょう。
—
お買い物のレジで例えてみよう
イメージしてください。あなたは今、スーパーのレジ打ちのアルバイトをしています。お客さんがカゴに入れて持ってきた商品の「個数」をチェックする場面です。
ケース1:論理和(`||`)は「厳しいお局さま」
論理和(`||`)は、JavaScriptにとっての「Falsy(お前はゼロだ、あるいは無効だ!)」な値をすべて厳しく弾き返すお局さまのような存在です。
論理和が「無効だ」と判断する(つまり、右側の「代わりの値」を採用してしまう)メンバーはこちら:
- `false` (ブール値の偽)
- `0` (数値のゼロ)
- `””` (空っぽの文字列)
- `null` (何もないよという意図的な不在)
- `undefined` (まだ値が定義されてないよ)
- `NaN` (数値じゃないよ)
さて、お買い物の例に戻りましょう。
お客さんが「りんご、0個です」とレジに持ってきたとします。「0個」って、買う数がゼロ個という意味で立派なデータですよね。
しかし、お局さま(`||`)はこう言います。
> 「ゼロ? そんなの何も無い(Falsy)のと一緒よ! 代わりに『1個』にしておきなさい!」
……勝手に個数を書き換えられてしまいました!これでは困りますよね。本当は「0個」と入力したかったのに。
ケース2:Null合体演算子(`??`)は「優しい店長」
一方、新しく登場したNull合体演算子(`??`)は、もっとおおらかな「優しい店長」です。
店長(`??`)が「おや、これはデータなしだな」と認めるのは、世の中のすべての値ではなく、この2つだけです。
- `null` (本当になんにもない)
- `undefined` (まだ決まってない)
それ以外の「0」や「false」、空文字の「””」は、「おっ、ちゃんと意味のある値が入ってるね!そのまま通しなさい!」と優しく受け入れてくれます。
先ほどのお客さんが「りんご、0個です」と持ってきたとき、優しい店長(`??`)ならこう言います。
> 「なるほど、0個なんだね。分かったよ、そのまま0個として処理するね」
ほら、こっちの方が人間の感覚にしっくりきませんか?
—
コードで違いを体感してみよう
百聞は一見にしかず。実際にコードを書いて、この2人の違いをこの目で確かめてみましょう。
以下のコードをブラウザのコンソールなどに貼り付けて、動きを見てみてください。
// 【ケースA:ユーザーが「0個」と入力した場合】
const itemCount = 0;
// 論理和(||)を使った場合
const resultOr = itemCount || 10;
console.log(resultOr);
// 出力結果: 10 (あれっ!? 「0」だったのに、勝手に「10」に書き換えられちゃった!)
// Null合体演算子(??)を使った場合
const resultNullish = itemCount ?? 10;
console.log(resultNullish);
// 出力結果: 0 (やった! 「0」という大切なデータをちゃんと守ってくれた!)
どうでしょう? `0` という数値を扱いたいとき、`||` を使ってしまうと意図せずデフォルト値(上の例では `10`)にすり替わってしまうんです。これが、現場で初心者がよくハマる「消える0(ゼロ)の罠」の正体です。
—
もう一つの罠:空文字(””)の扱い
数え切れないほどのWebサイトを作ってきた私たちプロも、かつては入力フォームの「お名前欄」などでこの問題に頭を抱えていました。
ユーザーが名前を入力せずに送信ボタンを押してしまい、値が空っぽの文字列 `””` になったとします。
const userName = “”;
// 論理和(||)
console.log(userName || “名無しさん”);
// 出力: “名無しさん” (空文字はFalsyなので、デフォルト値になる)
// Null合体演算子(??)
console.log(userName ?? “名無しさん”);
// 出力: “” (あれっ!? 空文字は null でも undefined でも無いので、そのまま “” が出力されちゃった!)
おっと!ここで注意が必要です。
「値が本当に何もない(`null` か `undefined`)ときだけデフォルト値を出したい」のが `??` の仕事です。そのため、「空文字 `””` のときもデフォルト値にしたい!」という場合は、`??` ではなく `||`(または明示的な文字数のチェック)を使う必要があるんです。
ここが、使い分けのいちばん大切なポイントですよ。
—
現場で迷ったときの「使い分けの指針」
では、実務ではどのようにこの2人を使い分ければいいのでしょうか? チーフアーキテクトからの実践的なアドバイスをまとめました。
1. 「数値(0や負の数)」や「真偽値(false)」をそのままデータとして生かしたいとき
- $\rightarrow$ 迷わず Null合体演算子(`??`)を使いましょう! (設定値のデフォルト値や、個数・スコアの判定に最適です)
2. 「空文字(`””`)」や「ゼロ(`0`)」も含めて、何かしら値が入っていなかったら全部デフォルト値に置き換えたいとき
- $\rightarrow$ これまで通り論理和(`||`)の出番です!
—
まとめ:つまずいても大丈夫、少しずつ慣れていこう
JavaScriptの型判定や演算子は、最初は覚えることが多くて複雑に感じるかもしれません。「あれ、どっちを使うんだっけ?」と手が止まるのは、あなたが真剣にコードと向き合っている証拠です。
もし忘れてしまったら、またこの記事の「お買い物のレジ(お局さまと優しい店長)」の例えを思い出してくださいね。
現代のモダンなJavaScript開発では、安全で確実なコードを書くために `??` を使う機会がぐっと増えています。ぜひあなたの引き出しにもこの道具をそっとしまって、日々のコーディングを楽しんでください。
それでは、また次の現場でお会いしましょう!Happy Hacking!

コメント