👻

もう怖くない、 「!!」 ・「??」 ・「||」 を完全攻略!

2023/12/14に公開

これは株式会社TimeTree Advent Calendar 2023の14日目の記事です。

https://qiita.com/advent-calendar/2023/timetree

はじめに

TimeTreeでフロントエンドエンジニアをしています、skitzvilleです。

今回初めてアドベントカレンダーに投稿をするにあたって、「何書けばいいんだ??」と頭を抱えていたところ、偶然にもエンジニアとして働き始めた当初の自分が残した苦悩の爪痕の様なメモが見つかりました。

今となっては当たり前の内容ではありますが、自分のように同じ部分で疑問を持った方の理解の助けになればなーということで記事を書ければと思います。

!!って何!?

イカつい見た目してますよね、初めて見た時は勢いにやられそうになりました。

double exclamation markだったりdouble bangと呼ばれるこの記述、実際のコードでは以下のような形で遭遇することがあるのかなと思います。

someFunction({enabled: !!accountId});

何が起こってるか、よりわかりやすいように以下のサンプルを用意しました。

const hello = "Hello";
console.log(!!hello); // true

const empty = "";
console.log(!!empty); // false

出力された値を見てもわかるように、!!オペレーターは「その後に続く変数・定数をbooleanに変換する」役割をしています。変換にあたっては、!!に続く値が以下のどれになるかでtrueかfalseかが決まります。

💡 Falseとして判定される

  • 空文字(””)
  • 0
  • null
  • undefined
  • NaN

💡 Trueとして判定される

  • オブジェクト
  • 配列
  • 空文字でない文字列(”anything”)
  • 0でない数字

??って何!?

またしてもミステリアスなやつが来ました。

なんて呼べばいいのかもわからないこの記述、Nullish Coalescing Operatorという名前があるようです。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing

おそらく実際のコードでは以下のような形で目にすることがあるのではないでしょうか。

someFunction({status: userStatus ?? "guest"});

またしても何が起こってるかわかりやすいように、以下のサンプルを用意しました。

const test = undefined;
const output = test ?? "Hello";

console.log(output); // Hello

上記のサンプルを見るとわかると思いますが、この?? のオペレーターは「左側の値がnullもしくはundefinedだった場合、右側の値を返す」という働きをするものです。

つまり上の例では?? の左側にあるtest をチェックし、値がundefinedもしくはnull であれば??の右側にある文字列を返すという動きをします。(今回はtest = undefinedなので文字列が出力されていますよね)

ただここで注意したいのは、あくまでnullundefinedが対象という点です。

そのため以下のような場合、testの値自体は空文字なのでfalsyですが、undefinednull のどちらにも該当しないため、”” がそのまま出力されることになります。

const test = "";
const output = test ?? "Hello";

console.log(output); // ""

待って、||ってやつもいた気がするけど!?

います。||

自分は普段double pipeとかって呼び方をしちゃってますが、こちらにもLogical Or Operatorという名前がついています。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR

おそらく実際のコードでは以下のような形で目にすることがあるのではないでしょうか。

someFunction({status: userStatus || "guest"});

くどいですが何が起こってるかわかりやすいように、以下のサンプルを用意しました。

const test = undefined;
const output = test || "Hello";

console.log(output); // Hello

この||オペレーターですが、働きは先ほど紹介した?? に似ていて、「左側の値がfalsyだった場合、右側の値を返す」という働きをしています。

上の例を見るとわかるように、test の値はundefined であるためfalsyとなり、”Hello”が出力されていますね。

ここでいうfalsyな値とは一般的にJavaScriptでfalseとして判定されるような以下の値を指しています。

- 空文字(””)
- 0
- null
- undefined
- NaN

試しにtestの値を上のどれかに書き換えてみても結果は同じになります。

const test = 0;
const output = test || "Hello";

console.log(output); // Hello

?? vs ||

使われ方が似ておりよく混同しやすいのがこの2つですが、以下の違いさえ頭に入れておけば理解がしやすいかと思います。

?? : 左側の値がundefinedもしくはnullだった場合、右側の値を返す

|| : 左側の値がfalsyだった場合、右側の値を返す

先ほどの例を元に考えると、

functionA({status: userStatus ?? "guest"});
functionB({status: userStatus || "guest"});

??を使用しているfunctionAでは、userStatusundefinedもしくはnull の場合に限って、statusを”guest”に設定していることがわかります。

一方||を使用するfunctionBでは、userStatusが仮に0”” であった場合でもstatusには”guest“が設定されます。

?? の方がundefinednullというより少ない対象に絞って、厳密にチェックをしているイメージですね。

終わりに

以上ざっくりとですが、!!??||の曲者3兄弟についての説明でした!

実際の業務でも頻繁に登場する基本的な記述ではありますが、初学者の方、JavaScriptに触れて間もない方にはとっつきにく部分でもあるかなと思います。
ただ実際に業務で触るコードでは頻繁に目にする表現でもあるため、「この表現ってなんなんだろう」と疑問に思われた方はぜひ本記事の内容を参考にしてみてください。

TimeTree Tech Blog

Discussion