はじめに
iimonフロントエンジニアの齋藤です。
業務をやっていく中でオプショナルチェーンを使う機会が多いため、オプショナルチェーンの色々を調べてみました。
背景
業務でVanila JS化(フレームワーク等を使用しない素のJavaScriptにコードを書き換えること)をする際に以下のようなjQueryのようなコードをVanila JS化をするとエラーが出ます。その際にオプショナルチェーンについて学ぶことがあったのでまとめました
以下はhogeElementのname要素からテキスト情報を取得しているコードです
jQueryコード
const bukkenName = $(hogeElement).find('.name').text();
JavaScript(Vanila Js)
const bukkenName = hogeElement.querySelector('.name').innerHTML;
→Object is possibly 'null’(オブジェクトは 'null' である可能性があります)
jQueryの場合、うまく作動します。
しかし素のJavaScriptではundefined
やnull
に対してプロパティアクセスを行うとエラーになります。
Javascriptでは該当するDOMがなかった場合には null が返ってくるので、メソッドチェーンが使えずにエラーになってしまいます。
→メソッドチェーンとは
JavaScriptでは(.)で表され、オブジェクトに対して複数のメソッドを続けて呼び出し、それらのメソッドが順番に実行され、最終的な結果を取得する方法のことです。
これを解決するためにはオプショナルチェーン(?.)というのものを使います。
オプショナルチェーン(optional chaining)とは
ES2020から新たに追加された機能で、?.
を用いてnull
やundefind
の可能性がある値へ安全にアクセスできる仕組みです。
公式→https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining
- 使用するタイミング
- オブジェクトのプロパティにアクセスし、そのプロパティが存在しない可能性があるとき
const user = { name: 'John', age: 30, address: { city: 'Tokyo', country: 'Japan' } }; const country = user.address.country; console.log(country);
user.address
が存在しない場合に、user.address.country
の参照がエラーとなります。そこで、オプショナルチェーンを使って以下のように書き換えることで、プロパティが存在しない場合でもエラーを回避することができます。
const user = { name: 'John', age: 30, address: { city: 'Tokyo', country: 'Japan' } }; const country = user?.address?.country; console.log(country);
ただ単にconsole.logで表示するだけならいいですが、実際に使われているコードではここで処理が止まったり、エラーになったりします
- 配列の要素にアクセスする際に、要素が存在しない可能性がある場合
エラーになる
const udf = undefined; const array = [1, 2, 3]; console.log(udf[1])
→ Uncaught TypeError: Cannot read properties of undefined (reading '1')
書き換えてエラーを回避(undefindになる)
const udf = undefined; const array = [1, 2, 3]; console.log(udf?.[1]);
- メリット
エラーの回避
存在しないプロパティや要素にアクセスしようとするとエラーが発生し、プログラムが中断される可能性があります。しかし、オプショナルチェーンを使用することで、プロパティや要素が存在しない場合でもエラーを回避して、プログラムを継続的に実行することができます。
コードの簡潔化
オプショナルチェーンを使用することで、コードをより簡潔に書くことができます。従来の方法では、存在しないプロパティや要素にアクセスする際に、事前に存在チェックを行ったり、条件分岐を書いたりする必要がありました。しかし、オプショナルチェーンを使うことで、このような冗長なコードを削減することができます。
if ( user && user.obj && user.obj.hoge ) { huga = user.obj.hoge.plan; } // 条件文の判定を、簡潔に書ける const city = user?.obj?.hoge?.plan;
上記のコードでは、user
とuser.obj
が存在し、user.obj.hoge
が存在する場合に、条件が満たされます。オプショナルチェーンを使わずに記述すると、ifの条件で都度チェックすると必要があります。ただし、この方法はネストが深くなるとコードが冗長になる可能性があるため、オプショナルチェーンを使用することを推奨します。オプショナルチェーンを利用すると、より簡潔で読みやすいコードを記述することができます。
短絡評価
左側を評価した時点で結果が確定したのであれば右側が評価されません。これを短絡評価と呼びます。したがって、そこになんらかの関数呼び出しや副作用があっても発生しません。
- オプショナルチェーン
値がnull
やundefined
だった場合に以降の処理を行わず、undefined
を返す
const a = { hoge: 'hoge' }; console.log(a?.hoge); console.log(a?.fuga); console.log(a.hogeFunc?.());
- aプロパティが存在しているのでhogeを返す
- fugaプロパティが存在していないので、以降の処理が短絡されて
undefind
を返す - hogeFuncプロパティが存在していないので、以降の処理が短絡されて
undefind
を返す
色々な短絡評価
falsyなオペランドに遭遇した時点で評価を終了する
console.log(false && true)//false
falsyな値: false
undefined
null
””
0
オペランド: 式で演算子の対象となっているもの、演算子の左右にある変数や数字のこと
左から右へと順にオペランドを評価して、truthyな値があればその時点で評価を終える
console.log(false || true)//true
truthyな値: falsyな値を除くすべての値
- null合体演算子(??)
nullかundefinedのオペランドに遭遇しなかった場合に処理を終了する
console.log(null ?? true); //true console.log(0 ?? 1); //0を返す
- オプショナルチェーンとnull合体演算子を組み合わせる
オプショナルチェーンとnull合体演算子を組み合わせると、オプショナルチェーンがundefined
を返したときに、デフォルト値を代入できます
const hoge = undefined; const huga = hoge?.huga ?? "aa"; console.log(huga);
最後に
オプショナルチェーンを使ってコードを簡潔に書き、プロパティに値が入ってこない可能性があるならば積極的に使用してエラーを防ぎつつ読みやすいコードを書いていきたいです