🔗

JS オプショナルチェーン(optional chaining)の豆知識

2022/09/16に公開

概要

JavaScriptのオプショナルチェーン(optional chaining)演算子について、意外と知られていないかもしれない細かい挙動2点について紹介します。

  1. 参照が無い時点で、以降のチェーンは読み込まれない
  2. 参照が無い場合の関数呼び出しは、引数の評価も実行されない

オプショナルチェーンとは

通常はオブジェクトのプロパティにアクセスする際に . の左側がnullまたはundefinedの場合に、エラーとなります。

オプショナルチェーン ?. を使うと、左側がnullishの場合にもエラーにならず、undefinedが返るため、短い書き方でプロパティにアクセスすることができます。

// userは { id: 1 } または null

// 通常のプロパティアクセス
user.id // => Uncaught TypeError: Cannot read properties of null (reading 'id') が発生し得る

// オプショナルチェーンでアクセス
user?.id // => 1 or undefined

// オプショナルチェーンを使わず、明示的にチェックする場合
user ? user.id : undefined // => 1 or undefined

豆知識

1. 参照が無い時点で、以降のチェーンは読み込まれない

// userは { id: 1, profile: { name: 'ユーザー1' } } または null

// nameにアクセスする際、2つ目の?はなくてもエラーにならない
user?.profile?.name // => 'ユーザー1' or undefined
user?.profile.name // => 'ユーザー1' or undefined

usernull の場合、 user?.profileundefined になるため、そこから .name と繋げるときには、 ?.name とする必要があるのかと思っていました。

しかし実際は、 usernull の場合、 user?.profile 以降の .name は読まれず、チェーン全体が undefined を返すため、 undefined.name のようなプロパティアクセスによるエラーが起きることはないようです。

※余談ですが、JSの ?. と似たような働きをするRubyの &. は、上記の場合 user&.profile&.name としないとエラーになるようです。

2. 参照が無い場合の関数呼び出しは、引数の評価も実行されない

// objは { func: 引数を受け取る関数 } または null
// calcValue()は、その引数に渡す値を計算する重い処理

// objがnullなら、calcValue()も実行されずにundefinedが返る
obj?.func(calcValue())

上記の通り、 ?. で関数を呼び出す時、左側がnullishであれば、関数呼び出しの引数の評価自体もされないようです。

似た場面として、Chromeのログレベルをwarnings以上にしている場合 console.log(calcValue()) は何も出力しませんが、それでも calcValue() 自体は実行されるようです。

それに比べると、 ?. による関数呼び出しは、必要な時のみ引数の評価をするので、無駄がなくて良いですね。

おわりに

以上、オプショナルチェーンについて最近知った豆知識でした。

一次情報で確認した訳ではなく、ChromeやNode.jsで実験して確認した内容ですので、もし間違っていることがありましたらご指摘をお願いいたします。

参考情報

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Discussion