入れ子のオブジェクトを安全に扱う

深いところを辿ると途中で落ちます。オプショナルチェーンで落ちないようにする方法、分割代入で必要な値だけ取り出す書き方、既定値の付け方と ?? と || の違いを確かめます。

実行して検証済み処理系Node 22.22.3対応ES2020難易度●●○○○目安9更新

実際のデータは入れ子になっています。深く辿るのは、そのままだと危険です。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
javascript
const data = { user: { profile: { name: 'あ' } } };

console.log(data.user.address.city);
TypeError: Cannot read properties of undefined (reading 'city')

途中の鍵が無いと落ちます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
undefined あ
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
0.0 0

data.user.addressundefined で、その city を読もうとしたからです。 落ちるのは最後の1段で、原因はその手前にあります。 → Cannot read properties of undefined

?. で落ちないようにする

?. は、左が nullundefined なら、そこで止めて undefined を返します

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
あ undefined undefined
javascript
console.log(data?.user?.profile?.name);

これをオプショナルチェーンと呼びます。

止まるのは nullundefined のときだけです。 0 や空文字では止まりません。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
未設定
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
0 10 "" "なし" false true

関数と配列にも使える

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
あ 20
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
東京

?.() は「関数があれば呼ぶ」、?.[] は「あれば取り出す」です。 無い関数を呼んでも落ちません。

使いすぎない

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
あ 既定値

全部に付けるのは、考えるのをやめている合図です。 data が必ずあると分かっているなら、そこに ?. は要りません。

本当は「無いはずがない」ところが undefined になっていても、?. が黙って隠します。 付けるのは「無いことがありうる」と分かっている場所だけにしてください。

既定値を付ける

?? は、左が nullundefined のときだけ右を返します。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
null 既定値
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
あ(東京) い(不明)

|| との違い

ここは必ず踏む落とし穴です。

||0・空文字・false も「無い」と見なします

  • 件数が 0 なのに 10 になる
  • 入力が空なのに「なし」に置き換わる
  • 設定を false にしたのに true になる

「値が無いとき」の既定値は ??、「偽のとき」の代替は || 迷ったら ?? です。

分割代入で取り出す

必要な値だけを、名前を付けて取り出せます。

入れ子も取り出せます。

ただし address が無いと落ちます。 深い分割代入は、 あることが確実なときだけにしてください。

名前を変える・既定値を付ける

  • name: userName別の名前で受け取る。他の変数と衝突するときに使う
  • nothing = '既定値'無いときだけ使われる

既定値が働くのはundefined のときだけです。null では働きません。

??null でも働き、分割代入の既定値は働きません。 ここが違います。

関数の引数で使う

分割代入がいちばん効くのは、関数の受け口です。

何を使うのかが、呼び出し側から見えます。 引数の順番を覚えなくてよくなるのも利点です。

まとめ

  • 途中の鍵が無いと落ちる。原因は落ちた場所の手前
  • ?.nullundefined のときだけ止まる。0 や空文字では止まらない
  • 全部に ?. を付けない。 隠すべきでない間違いまで隠れる
  • 既定値は ??||0・空文字・false も置き換える
  • 分割代入の既定値は undefined のときだけ働く(null では働かない)
  • 関数の引数で使うと、何を使うのかが呼び出し側から見える

次に学ぶ

オブジェクトの中身を全部まとめて扱う方法を学びます。 Object.keys() / values() / entries() で回し、 配列のメソッドと組み合わせて変換する形までやります。

第3回: オブジェクトを回す・変換する

この記事の根拠

  1. Optional Chains — ECMAScript® 2026 Language Specificationtc39.es
  2. Destructuring Binding Patterns — ECMAScript® 2026 Language Specificationtc39.es
  3. Nullish coalescing operator — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)