JavaScript の ? を完全攻略 ! ?. と ?? の違いと使い方

やたらと ? が多いプログラム
皆さんは下記 Javascript の実行結果と何が出力されるかわかりますか?
const a = { b: "c" };
const b = { c: "d" };
console.log(a?.b?.c ?? b?.c ?? "?");
このプログラムには Javascript の ? を使う演算子が 2 種類含まれています。
ひとつづつ解説したうえで、記事の最後に上記プログラムの答えを記述します。
オプショナルチェーン ( ?. )
JavaScript では null や undefined のプロパティに対してアクセスすると、例外が発生してプログラムが止まってしまいます。
そのため、通常 null かもしれない値にアクセスする場合は下記のように null チェックを行います。
if (cat !== null) console.log(cat.name);
これをオプショナルチェーンで記述すると下記のように短く書くことができます。
console.log(cat?.name);
cat が null や undefined だった場合でも例外は発生せず、コンソールには undefined と出力されます。
null 合体演算子 ( ?? )
JavaScript で、もし変数の値が null でなければ変数を参照し、null だった場合はほかの値を利用することはよくあると思います。
この時に三項演算子を利用すると以下のように記述することができます。
console.log(cat != null ? cat : "猫");
これを null 合体演算子を用いて記述することで下記のようによりスマートに記述することができます。
console.log(cat ?? "猫");
null 合体演算子は左辺が null または undefined の時に、右辺を返します。
値が無い場合のデフォルト値を設定するときによく利用します。
まとめ
これらを踏まえて最初のコードをもう一度見てみると何が起こるのかわかると思います。
const a = { b: "c" };
const b = { c: "d" };
console.log(a?.b?.c ?? b?.c ?? "?");
まず、一番左 ( a?.b?.c ) について a は b を持っていますが、b は c を持たないため、オプショナルチェーンによって undefined が返されます。
真ん中 ( a?.b?.c ?? b?.c ) は、左辺が undefined なので b?.c が返されます。
b は c を持っているので、結果 b.c に格納されている "d" が出力されます。
一番右 ( ?? "?" ) は b?.c が undefined ではないため評価されません。
上記のようにオプショナルチェーンと null 合体演算子は合わせてよく使うので、覚えておくと便利です。