Optional chaining とは何か(まずイメージから)
Optional chaining(オプショナルチェイニング)は?. という記号で書く、「存在しないかもしれないプロパティに安全にアクセスするための仕組み」 です。
const user = { profile: { name: "Alice" } };
console.log(user.profile?.name); // "Alice"
console.log(user.address?.city); // undefined(エラーにならない!)
JavaScript普通に user.address.city と書くと、address が undefined のときに
「Cannot read properties of undefined」 というエラーで落ちます。
?. を使うと、
「もし左側が null か undefined なら、そこで止めて undefined を返す」
という安全な動きになります。
ここが重要です。
「あるかもしれない、ないかもしれない」深いプロパティにアクセスするときは、とりあえず ?. を思い出す。
これだけで、かなりの「よくあるエラー」を避けられます。
なぜ Optional chaining が必要なのか
よくあるエラー:「undefined の何かを読もうとして落ちる」
JSON や API からのデータを扱っていると、
こんなコードを書きたくなります。
const city = user.address.city;
JavaScriptでも user.address が存在しない(undefined)場合、
Cannot read properties of undefined (reading 'city')
JavaScriptのようなエラーになってしまいます。
こういうエラーは、実務では本当によく出ます。
旧式の対処:if を何重にも書く
昔は、こうやってガードしていました。
let city;
if (user && user.address && user.address.city) {
city = user.address.city;
} else {
city = "不明";
}
JavaScript動きますが、見た目がかなりつらいですよね。
ネストが深くなるほど、&& の地獄になっていきます。
Optional chaining を使うとどうなるか
同じことを Optional chaining で書くと、こうなります。
const city = user.address?.city ?? "不明";
JavaScriptuser.address?.city
→addressがあればcityを読む
→ なければundefinedを返す(エラーにはしない)?? "不明"
→ 左がnull/undefinedなら"不明"を使う
ここが重要です。
「深いところまであるかどうか分からないデータ」には、?. と ?? を組み合わせるのが ES2020 以降の定番パターン です。
基本文法:obj?.prop と obj?.[key] と func?.()
プロパティアクセス:obj?.prop
一番よく使うのがこれです。
const user = { profile: { name: "Alice" } };
console.log(user.profile?.name); // "Alice"
console.log(user.address?.city); // undefined(エラーにならない)
JavaScriptuser.address?.city の場合、
user.addressがnull/undefined→ 全体がundefined- それ以外(オブジェクトなど) → その
cityを読む
という動きになります。
ブラケット記法:obj?.[key]
キー名が変数に入っている場合や、
スペースを含むプロパティ名などにはブラケット記法を使います。
const data = { settings: { "user-name": "Alice" } };
const key = "user-name";
console.log(data.settings?.[key]); // "Alice"
console.log(data.missing?.[key]); // undefined(エラーにならない)
console.log(data.settings?.["age"]); // undefined
JavaScriptobj?.[key] は、
「obj が null/undefined なら undefined、それ以外なら obj[key]」という動きです。
関数呼び出し:func?.()
「あるかどうか分からない関数」を呼ぶときにも使えます。
const callbacks = {
onClick: () => console.log("クリックされました"),
};
callbacks.onClick?.(); // あれば呼ぶ
callbacks.onHover?.(); // なくてもエラーにならない
JavaScriptfunc?.() は、
funcが関数なら呼ぶfuncがnull/undefinedなら何もせずundefinedを返す
という振る舞いです。
ここが重要です。
「オプションで渡されるコールバック」「あってもなくてもよいイベントハンドラ」には func?.() が刺さる。
「もしあれば」という意図がコードからも一目瞭然です。
ネストが深いときにこそ威力を発揮する
典型例:API レスポンスの安全アクセス
API からこんなデータが返ってくるとします。
const user = {
profile: {
name: "Alice",
address: {
city: "Tokyo",
},
},
};
JavaScriptでも、環境によっては address がなかったり、profile 自体がなかったりするかもしれません。
昔なら:
let city;
if (
user &&
user.profile &&
user.profile.address &&
user.profile.address.city
) {
city = user.profile.address.city;
} else {
city = "不明";
}
JavaScriptOptional chaining + null 合体演算子なら:
const city = user.profile?.address?.city ?? "不明";
JavaScript読みやすさの差は、かなり大きいです。
チェーンの途中で止まるイメージ
user.profile?.address?.city の評価は、ざっくりこうです。
user.profileを読む(ここでエラーにはならない前提)- その結果が
null/undefinedなら、そこで全体をundefinedにして止める - そうでなければ
.addressに進む - また
?.があるので、addressがnull/undefinedなら止める - そうでなければ
.cityを読む
ここが重要です。?. は「安全な橋渡し」みたいなもの。
その地点の手前で川(null/undefined)が切れていたら、それ以上向こうには渡らない。
Optional chaining と他の演算子の組み合わせ
?. と ??(null 合体演算子)
Optional chaining で undefined になってしまったときの「代わりの値」を指定するのに、?? が使えます。
const city = user.profile?.address?.city ?? "不明";
JavaScript?? の左側が null または undefined のときだけ、右側が使われます。
空文字や 0 などはそのまま有効な値として扱われます。
const config = { retries: 0 };
const count1 = config.retries || 3; // 0 が「偽」とみなされて 3 になる
const count2 = config.retries ?? 3; // 0 をそのまま採用 → 0
JavaScript?. と || を混ぜたくなるときの注意
|| は「偽っぽい値(0, “”, false など)も全部ダメ扱い」するので、
設定のデフォルト値などでは、?? の方が意図に合っていることが多いです。
誤解を避けるためにも、
「不在(null/undefined)にだけデフォルト値を入れたい」ときは ??
と覚えておくのがおすすめです。
Optional chaining の落とし穴・注意点
何でもかんでも ?. を付ければいいわけではない
user?.profile?.name のように、
「あるかどうか本当に分からない」場所に使うのは良いのですが、
全部にクセで ?. を付けてしまうと、
バグの早期発見を妨げることがあります。
例えば、本来絶対にいるはずの user が undefined になってしまったとき、
user.name→ そこでエラーになってすぐ気付けるuser?.name→undefinedになってしまい、どこでミスったのか分かりにくくなる
ということが起きます。
ここが重要です。
Optional chaining は「本当に Optional なもの」にだけ使う。
「必須のもの」に使うとバグを隠すことになる。
左側が「必ずある」なら、普通の . でいい
例えば:
const user = getUser(); // ここが「必ず User を返す」契約なら
console.log(user?.name); // よりも
console.log(user.name); // のほうがいい(おかしいときにすぐ落ちる)
JavaScript設計として「必ずあるはず」のものには、
あえて Optional chaining を使わず、
異常時にはエラーになってもらった方が、デバッグがしやすくなります。
短い例題で手を動かしてみる
例1:ネストされた配列・オブジェクト
const data = {
items: [
{ id: 1, name: "A" },
{ id: 2, name: "B" },
],
};
const firstName = data.items?.[0]?.name ?? "なし";
const thirdName = data.items?.[2]?.name ?? "なし";
console.log(firstName); // "A"
console.log(thirdName); // "なし"
JavaScriptitems?.[2]?.name の部分に注目してください。
itemsがなければ →undefined[2]がなければ →undefined.nameがなければ →undefined
どこで途切れても、全体が undefined になり、
最終的に ?? "なし" が適用されます。
例2:存在するか分からないイベントハンドラ
function runCallbacks(callbacks) {
callbacks.onStart?.();
console.log("メイン処理");
callbacks.onFinish?.();
}
runCallbacks({
onStart() {
console.log("開始");
},
// onFinish は省略
});
// 開始
// メイン処理
JavaScriptonFinish がなくてもエラーにならず、
「あるときだけ実行される」のが Optional chaining の美味しいところです。
まとめ
Optional chaining(?.)の本質は、
「null / undefined かもしれないものに、安全にアクセスするためのショートカット」 です。
押さえておきたいポイントは:
obj?.prop/obj?.[key]/func?.()の 3 形態がある- 途中で
null/undefinedに遭遇したら、そこで評価を止めてundefinedを返す(エラーにしない) - 深くネストしたオブジェクト・API レスポンス・オプションのコールバックなどで強力
??(null 合体演算子)と組み合わせて「デフォルト値」を書くのが定番- なんでも
?.にするとバグを隠すので、「本当に存在が optional な場合」にだけ使う
まずは、
- 素直に書くと
Cannot read properties of undefinedが出てしまうコード user && user.address && user.address.cityみたいなガードだらけのコード
を一つ見つけて、それを
const city = user.address?.city ?? "不明";
JavaScriptのように書き直してみてください。
その一歩で、Optional chaining の「気持ちよさ」がかなりはっきり見えてきます。

