JavaScript | ES6+ 文法:その他の ES6+ 機能 – Nullish coalescing

JavaScript JavaScript
スポンサーリンク

Nullish coalescing とは何か(まずイメージから)

Nullish coalescing(ヌリッシュ・コアレスシング)は
?? という演算子で書く、
「値が null または undefined のときだけ、代わりの値を使う」ための仕組みです。

一番シンプルな例はこれです。

const input = undefined;
const value = input ?? "デフォルト";

console.log(value); // "デフォルト"
JavaScript

inputnullundefined なら、「右側の "デフォルト" を使う」という意味になります。
逆に、0""false のような「値としては存在しているもの」は、そのまま使います。

ここが重要です。
「“値がない” 本当の意味での “空”(null / undefined)のときだけデフォルトを使いたい」
という場面では、?? がベストです。

|| と ?? は何が違うのか(ここをしっかり)

従来よく使われていた || の問題点

ES2020 以前は、「デフォルト値」を書くのに || をよく使っていました。

const input = 0;
const value = input || 10;

console.log(value); // 10
JavaScript

ここで問題なのは、input0 でも、"" でも、false でも、
「全部ダメな値」とみなされて右側が使われてしまうことです。

|| は「左が falsy(偽っぽい値)」なら、右を使う、というルールだからです。
falsy に含まれるのは、0, "", false, null, undefined, NaN などです。

?? は「null / undefined だけ」を特別扱いする

?? はルールがはっきりしています。

左側が null または undefined のときだけ、右側を使う。
それ以外の値(0, “”, false など)は、ちゃんと「ある値」として扱う。

例えば次のコードを見てください。

console.log(0 || 10);        // 10
console.log(0 ?? 10);        // 0

console.log("" || "空文字"); // "空文字"
console.log("" ?? "空文字"); // ""

console.log(false || true);  // true
console.log(false ?? true);  // false

console.log(null || "N");    // "N"
console.log(null ?? "N");    // "N"

console.log(undefined || "U"); // "U"
console.log(undefined ?? "U"); // "U"
JavaScript

「0 や空文字は有効な値として認めたい。
本当に “ない” とき(null / undefined)だけデフォルトにしたい。」
という場面では、?? を選ぶべきだと分かるはずです。

ここが重要です。
|| は「偽っぽい値なら全部ダメ」、
?? は「本当に不在(null / undefined)だけ特別扱い」。
この違いを理解すると、どこでどちらを使うかの判断が一気に楽になります。

基本形:左 ?? 右 の読み方と典型パターン

基本の読み方

a ?? b は、「a が null / undefined なら b、それ以外なら a」という意味です。

const a = null;
const b = a ?? "デフォルト";
console.log(b); // "デフォルト"
JavaScript

もう少しパターンを変えてみます。

console.log(undefined ?? "X"); // "X"
console.log(null ?? "X");      // "X"

console.log(0 ?? 10);          // 0
console.log("" ?? "EMPTY");    // ""
console.log(false ?? true);    // false
JavaScript

「0 や false も尊重したい」というときに ?? は非常に強力です。

設定値・オプションのデフォルトと相性が良い

例えば、設定オブジェクトからリトライ回数を読み出すコードを考えます。

const config = { retries: 0 };

// `||` で書くと…
const count1 = config.retries || 3;  // 0 が「ダメ」とみなされて 3 になる

// `??` で書くと…
const count2 = config.retries ?? 3;  // 0 は有効な値としてそのまま使う

console.log(count1); // 3
console.log(count2); // 0
JavaScript

ここで「0 回リトライ」という設定もアリなら、?? の方が正しいです。
|| を使うと、0 や “” が無条件に「不正な値」の扱いになってしまいます。

Optional chaining との組み合わせ(超よく使うパターン)

?. + ?? で「安全アクセス+デフォルト」

API レスポンスなどで、深いプロパティに安全にアクセスしつつ、
なかったときにはデフォルトを使いたい、という場面はとても多いです。

そんなときは Optional chaining(?.)と ?? を合わせて使います。

例を見てみます。

const user = {
  profile: {
    name: "Alice",
    address: {
      city: "Tokyo",
    },
  },
};

// address がないかもしれない
const city = user.profile?.address?.city ?? "不明";

console.log(city); // "Tokyo"
JavaScript

user.profile?.address?.city 部分は
どこかで null / undefined に出会ったらそこで止まり、全体が undefined になります。
そのあと ?? "不明" で、「なかったら不明」と補っているわけです。

profile がない、address がない、city がない、どの場合も安全に「不明」になります。

ここが重要です。
「あるか分からない深いプロパティ」には ?.
「なかったときの埋め草」には ??
このコンビは、実務で頻出する「防御的なコード」を非常に短く、読みやすくしてくれます。

実際のコードでの使いどころを具体的に見る

例1:ユーザーのニックネームがなければ本名、それもなければ “名無し”

const user = {
  // nickname: "Alice-chan",
  name: "Alice",
};

const nickname = user.nickname ?? user.name ?? "名無し";

console.log(nickname); // "Alice"
JavaScript

user.nickname が null / undefined なら user.name を見て、
それもなければ "名無し" になります。

同じことを || で書くと、「空文字のニックネーム」や「空文字の名前」も潰してしまう可能性があります。

例2:設定オブジェクトから安全に値を読む

const defaultConfig = {
  theme: "light",
  pageSize: 10,
};

function buildConfig(userConfig) {
  return {
    theme: userConfig.theme ?? defaultConfig.theme,
    pageSize: userConfig.pageSize ?? defaultConfig.pageSize,
  };
}

console.log(buildConfig({ theme: "dark" }));      // { theme: "dark", pageSize: 10 }
console.log(buildConfig({ pageSize: 0 }));        // { theme: "light", pageSize: 0 }
console.log(buildConfig({ pageSize: undefined })); // { theme: "light", pageSize: 10 }
JavaScript

ここでは、pageSize: 0 は「有効な値」として扱いたいので、そのまま残します。
もし || を使っていたら、0 が「ダメ」とされて 10 に置き換えられてしまいます。

例3:フォームの入力値を扱う

const form = {
  age: "",      // ユーザーが空のまま送信した
  height: "0",  // 0 と入力した
};

const age = form.age ?? "未入力";
const height = form.height ?? "未入力";

console.log(age);    // ""(空文字として扱う。判定は別でやる)
console.log(height); // "0"
JavaScript

ここで || を使うと、
空文字 """0" の扱いが変になりがちです。

?? を使うことで、「入力が全く来ていない(null/undefined)」と
「ユーザーが空文字や 0 を入れてきた」を、きちんと区別できます。

注意点と書き方のコツ

?? は優先順位に注意(カッコで明示する)

??||&& などを混在させるときは、
優先順位のルールがややこしくなるので、カッコを使って意図をはっきりさせましょう。

例えばこうです。

const a = null;
const b = 0;

// 良くない(読み手が悩む)
const value1 = a ?? b || 10;

// 意図をカッコで示す
const value2 = (a ?? b) || 10;
const value3 = a ?? (b || 10);
JavaScript

自分の頭の中で思っている順番を、カッコでそのまま表現してしまうのが安全です。

「null / undefined だけが “不在”」という前提を忘れない

?? は「null と undefined だけを不在扱いする」演算子です。
つまり、「0 や空文字も不在扱いしたい」という要件なら、?? は向きません。

その場合は、ちゃんと自分で条件を書くか、用途に応じて || を使うことも選択肢になります。

ここが重要です。
「どこまでを “ないもの” と見なすか」は、仕様の一部です。
?? を使うときは、「本当に null / undefined だけを特別扱いしたいか?」を一度自分に問い返してください。

まとめ

Nullish coalescing 演算子 ?? の本質は、
「本当に値が存在しないとき(null / undefined)だけ、デフォルト値にフォールバックする」ことです。

押さえておきたいポイントは次の通りです。

a ?? b は「a が null / undefined なら b、それ以外なら a」
|| は「0, “”, false も含めた falsy を全部ダメ扱いする」が、?? は null / undefined だけを不在扱いする
設定値、ユーザー入力、API レスポンスなどで「0 や空文字も正当な値」として扱いたいときに特に有効
Optional chaining(?.)と組み合わせると、「安全アクセス+デフォルト値」をとても短く書ける
何でもかんでも ?? ではなく、「本当に null / undefined だけに反応させたいのか?」を意識して使う

まずは、自分のコードの中で「|| でデフォルト値を入れているところ」を一つ見つけて、
そこを ?? に変えてみてください。
「0 や空文字の扱い」がどう変わるかを体感すると、
?? を使うべき場面と、|| を使うべき場面が、かなりクリアに見えてきます。

タイトルとURLをコピーしました