Null合体演算子(??)とは?「使い方」などを分かりやすく解説!

JavaScriptやTypeScriptのコードを見ているとはてな2つ(??)の箇所を見かけることがあります。このはてな2つ(??)は『Null合体演算子』と呼ばれています。

この記事ではJavaScriptの『Null合体演算子』について、

  • Null合体演算子(??)とは
  • Null合体演算子(??)と論理OR演算子(||)の「違い」と「使い分け」
  • Null合体演算子(??)の特徴

などをサンプルコードを用いて分かりやすく説明するように心掛けています。ご参考になれば幸いです

Null合体演算子(??)とは

Null合体演算子(??)は??の左側の値がnullまたはundefinedの場合には??の右側の値を返し、それ以外の場合には??の左側の値を返す演算子です。

以下にNull合体演算子(??)を用いたサンプルコードを示しています。以下のサンプルコードを見れば、Null合体演算子(??)の特徴が分かります。

// nullの場合
const dataNull = null;
const resultA = dataNull ?? 'defaultValue';
console.log(resultA); // ログ出力: defaultValue

// undefinedの場合
const dataUndefined = undefined;
const resultB = dataUndefined ?? 'defaultValue';
console.log(resultB); // ログ出力: defaultValue

// nullやundefined以外の場合
const data = 'hello';
const resultC = data ?? 'defaultValue';
console.log(resultC); // ログ出力: hello

dataNullの値はnullなので、??の右側の値を返しています。同様にdataUndefinedの値はundefinedなので、??の右側の値を返しています。

一方、dataの値はnullundefinedではないので、??の左側の値を返しています。

なお、Null合体演算子(??)を用いずに同じ動作をしたい場合には、以下のように記述します。

// nullの場合
const dataNull = null;
const resultA = (dataNull !== null && dataNull !== undefined) ? dataNull : 'defaultValue';
console.log(resultA); // ログ出力: defaultValue

// undefinedの場合
const dataUndefined = undefined;
const resultB = (dataUndefined !== null && dataUndefined !== undefined) ? dataUndefined : 'defaultValue';
console.log(resultB); // ログ出力: defaultValue

// nullやundefined以外の場合
const data = 'hello';
const resultC = (data !== null && data !== undefined) ? data : 'defaultValue';
console.log(resultC); // ログ出力: hello

上記のサンプルコードでは、三項演算子(?:)を使用しています。各変数がnullまたはundefinedでないことを確認し、その条件が真の場合はその変数の値を、偽の場合はデフォルト値(この例では'defaultValue')を返しています。これにより、Null合体演算子(??)と同様の結果を得ることができます。

補足

  • Null合体演算子は英語で「Nullish Coalescing Operator」と書きます。
  • Null合体演算子はES2020(ECMAScript 2020)の仕様で追加されました。

Null合体演算子(??)と論理OR演算子(||)の「違い」と「使い分け」

Null合体演算子(??)がES2020で追加される前、同じような機能を提供する際には論理OR演算子(||)が使われていました。

では、Null合体演算子(??)と論理OR演算子(||)の違いは何でしょうか?

論理OR演算子(||)は||の左側の値がnullまたはundefinedに限らず以下に示すfalsyな値の場合には??の右側の値を返し、それ以外の場合には||の左側の値を返す演算子です。

falsyな値

  • null
  • undefined
  • false
  • NaN
  • 0, -0, 0n
  • 空文字("", '', ``)

そのため、論理OR演算子(||)を用いる場合、0や空文字("", '', ``)などを正しい値として扱いたい時に予期せぬ結果を引き起こす可能性があります。

一方、Null合体演算子(??)を用いると、??の左側の値がnullまたはundefinedの場合(その他のfalsyな値は含みません)には??の右側の値を返し、それ以外の場合には??の左側の値を返すので、論理OR演算子(||)を用いることによる潜在的な危険を回避することができます。

では実際に以下のサンプルコードでNull合体演算子(??)と論理OR演算子(||)の違いを確認してみましょう。

// nullやundefined以外のfalsyの値(例えば:0)の場合
const data = 0;

// Null合体演算子(??)を用いた時
const resultA = data ?? 'defaultValue';
console.log(resultA); // ログ出力: 0

// 論理OR演算子(||)を用いた時
const resultB = data || 'defaultValue';
console.log(resultB); // ログ出力: defaultValue

Null合体演算子(??)を用いると0が返されていますが、論理OR演算子(||)を用いるとデフォルト値であるdefaultValueが返されています。

Null合体演算子(??)と論理OR演算子(||)の「使い分け」

falsyな値をどこまで許容させるかでNull合体演算子(??)と論理OR演算子(||)を使い分けます。

nullまたはundefined以外のfalsyな値をそのまま保持したい時にはNull合体演算子(??)を使います。

一方、falsyな値の場合にデフォルト値を設定したい場合には論理OR演算子(||)を使います。

Null合体演算子(??)の特徴

Null合体演算子(??)の特徴を以下に示します。

  • 短絡評価を行う
  • Null合体演算子(??)は論理AND演算子(&&)や論理OR演算子(||)と同時に使えない

各特長について順番に説明します。

短絡評価を行う

Null合体演算子(??)は論理OR演算子(||)や論理AND演算子(&&)と同様に短絡評価されます。

そのため、??の左側の値がnullまたはundefined以外の場合には、??の右側の式は評価されません。

サンプルコードを以下に示します。

// nullの場合
const dataNull = null;
dataNull ?? console.log('null'); // ログ出力: null

// undefinedの場合
const dataUndefined = undefined;
dataUndefined ?? console.log('undefined'); // ログ出力: undefined

// nullやundefined以外の場合
const data = 'hello';
data ?? console.log('hello'); // 短絡評価により、ログ出力されない

上記のサンプルコードを見ると、??の左側の値がnullまたはundefinedの場合には、??の右側の式が評価されるためログ出力されますが、??の左側の値がnullまたはundefined以外の場合には、??の右側の式は評価されないので、ログ出力されないことが分かります。

Null合体演算子(??)は論理AND演算子(&&)や論理OR演算子(||)と同時に使えない

Null合体演算子(??)を論理AND演算子(&&)や論理OR演算子(||)と同時に使用すると、SyntaxErrorが発生します。サンプルコードを以下に示します。

const resultA = 'Hello' && undefined ?? 'defaultValue';
const resultB = '' || undefined ?? 'defaultValue';
console.log(resultA); 
console.log(resultB);
// 以下のエラーが発生する
// Uncaught SyntaxError: Unexpected token '??'

以下のサンプルコードに示すように、括弧を付けて明示的に優先順位をつけると、SyntaxErrorは発生しません。

const resultA = ('Hello' && undefined) ?? 'defaultValue';
const resultB = ('' || undefined) ?? 'defaultValue';
console.log(resultA); // ログ出力: defaultValue
console.log(resultB); // ログ出力: defaultValue

上記のサンプルコードにおいて、&&の左側の値がfalsyな値ではないので、&&の右側の値(undefined)が返されます。その結果、??の左側の値がundefinedになるので、??の右側の値('defaultValue')が返されています。また、||の左側の値がfalsyな値なので、||の右側の値(undefined)が返されます。その結果、??の左側の値がundefinedになるので、??の右側の値('defaultValue')が返されています。

論理AND演算子(&&)と論理OR演算子(||)の違い

論理AND演算子(&&)は&&の左側の値がfalsyの値の場合には&&左側の値を返し、それ以外の場合には&&右側の値を返す演算子です。

一方、論理OR演算子(||)は||の左側の値がfalsyの値の場合には||左側の値を返し、それ以外の場合には||右側の値を返す演算子です。

本記事のまとめ

この記事ではJavaScriptの『Null合体演算子』について、以下の内容を説明しました。

  • Null合体演算子(??)とは
  • Null合体演算子(??)と論理OR演算子(||)の「違い」と「使い分け」
  • Null合体演算子(??)の特徴

お読み頂きありがとうございました。