2021年11月9日 JavaScript (JS Primer) Optional chaining演算子
プロパティの値がundefinedかどうか確認しプロパティの存在を確認する
if文を使うことで、プロパティの値がundefinedかどうか確認できます。プロパティの値があることが前提ならばundefinedかどうかを確認することでプロパティの存在の有無を確認する事になるからです。 以下のif文では、プロパティの値が存在しないことによる例外を発生させないために&&演算子を使っています。
function printWidgetTitle(widget) { // 例外を避けるために`widget`のプロパティの存在を順番に確認してから、値を表示しています。 if (widget.window !== undefined && widget.window.title !== undefined) { console.log(`ウィジェットのタイトルは${widget.window.title}です`); } else { console.log("ウィジェットのタイトルは未定義です"); } } // タイトルが定義されているwidgetです。 printWidgetTitle({ window: { title: "Book Viewer" } }); // タイトルが未定義のwidget printWidgetTitle({ // タイトルが定義されてない空のオブジェクトです。 }); // => ウィジェットのタイトルはBook Viewerです。 // => ウィジェットのタイトルは未定義です。
論理積と??の復習
論理積 &&
両辺がtrueの場合にtrue、左辺がfalseならそのままfalseを返します。??
Nullish coalescing演算子(??
)は、左辺の値がnullishであるならば、右辺の評価結果を返します。 nullishとは、評価結果がnull
またはundefined
となる値のことです。
Optional chaining演算子(?.)
Optional chaining演算子は、レシーバがundefined or nullなら、undefinedを返す演算子です。私達は、これを直感的に思い出しやすくするために、「あるの?演算子」と呼びました。
Optional chaining a.k.a.あるの?演算子です。
?.のたびに『あるの?』と聞いてきて、あれば右辺に行き、なければそこで処理を終えてundefinedを返します。なので、あるの?演算子と名付けました。 これを使う事で、プロパティの有無を確認することができ、冒頭のコードプロックのif文が短くわかりやすく書くことができます。
const obj = { a: { b: "objのaプロパティのbプロパティ" } }; // obj.a.b は存在するので、その評価結果を返します。 console.log(obj?.a?.b); // => "objのaプロパティのbプロパティ" // 存在しないプロパティのネストも`undefined`を返します。 // ドット記法の場合は例外が発生してしまいます。 console.log(obj?.notFound?.notFound); // => undefined // undefinedやnullはnullishなので、`undefined`を返します。 console.log(undefined?.notFound?.notFound); // => undefined console.log(null?.notFound?.notFound); // => undefined
先ほどのウィジェットのタイトルを表示する関数もOptional chaining演算子(?.)を使うと、if文を使わずに書けます。
function printWidgetTitle(widget) { const title = widget?.window?.title ?? "未定義"; console.log(`ウィジェットのタイトルは${title}です`); } printWidgetTitle({ window: { title: "Book Viewer" } }); // "ウィジェットのタイトルはBook Viewerです" と出力されます。 printWidgetTitle({ // タイトルが定義されてない空のオブジェクト }); // "ウィジェットのタイトルは未定義です" と出力されます。
Optional chaining演算子(?.)feat.ブラケット記法()
Optional chaining演算子(?.)はブラケット記法()と組み合わせることもできます。
const languages = { ja: { hello: "こんにちは!" }, en: { hello: "Hello!" } }; const langJapanese = "ja"; const langKorean = "ko"; const messageKey = "hello"; // Optional chaining演算子(`?.`)とブラケット記法を組みわせた書き方です。 console.log(languages?.[langJapanese]?.[messageKey]); // => "こんにちは!" // `languages`に`ko`プロパティが定義されていないため、`undefined`を返します。 console.log(languages?.[langKorean]?.[messageKey]); // => undefined // 「メモとして使いたい」 console.log(languages?.ja?.hello); // => "こんにちは!" console.log(languages?.["ja"]?.["hello"]); // => "こんにちは!"