JS オプショナルチェーン(optional chaining)の豆知識
概要
JavaScriptのオプショナルチェーン(optional chaining)演算子について、意外と知られていないかもしれない細かい挙動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
user
が null
の場合、 user?.profile
が undefined
になるため、そこから .name
と繋げるときには、 ?.name
とする必要があるのかと思っていました。
しかし実際は、 user
が null
の場合、 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で実験して確認した内容ですので、もし間違っていることがありましたらご指摘をお願いいたします。
参考情報
Discussion