iimon TECH BLOG

iimonエンジニアが得られた経験や知識を共有して世の中をイイモンにしていくためのブログです

オプショナルチェーンを使いこなす

はじめに


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ではundefinednull に対してプロパティアクセスを行うとエラーになります。

Javascriptでは該当するDOMがなかった場合には null が返ってくるので、メソッドチェーンが使えずにエラーになってしまいます。

→メソッドチェーンとは

JavaScriptでは(.)で表され、オブジェクトに対して複数のメソッドを続けて呼び出し、それらのメソッドが順番に実行され、最終的な結果を取得する方法のことです。

これを解決するためにはオプショナルチェーン(?.)というのものを使います。


オプショナルチェーン(optional chaining)とは


ES2020から新たに追加された機能で、?. を用いてnullundefind の可能性がある値へ安全にアクセスできる仕組みです。

公式→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で表示するだけならいいですが、実際に使われているコードではここで処理が止まったり、エラーになったりします

  1. 配列の要素にアクセスする際に、要素が存在しない可能性がある場合

エラーになる

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;

上記のコードでは、useruser.objが存在し、user.obj.hogeが存在する場合に、条件が満たされます。オプショナルチェーンを使わずに記述すると、ifの条件で都度チェックすると必要があります。ただし、この方法はネストが深くなるとコードが冗長になる可能性があるため、オプショナルチェーンを使用することを推奨します。オプショナルチェーンを利用すると、より簡潔で読みやすいコードを記述することができます。

短絡評価


左側を評価した時点で結果が確定したのであれば右側が評価されません。これを短絡評価と呼びます。したがって、そこになんらかの関数呼び出しや副作用があっても発生しません。

  • オプショナルチェーン

値がnullundefinedだった場合に以降の処理を行わず、undefined を返す

const a = {
    hoge: 'hoge'
};

console.log(a?.hoge);
console.log(a?.fuga);
console.log(a.hogeFunc?.());
  1. aプロパティが存在しているのでhogeを返す
  2. fugaプロパティが存在していないので、以降の処理が短絡されてundefind を返す
  3. hogeFuncプロパティが存在していないので、以降の処理が短絡されてundefind を返す

色々な短絡評価

falsyなオペランドに遭遇した時点で評価を終了する

console.log(false && true)//false

falsyな値: false undefined null ”” 0

オペランド: 式で演算子の対象となっているもの、演算子の左右にある変数や数字のこと

左から右へと順にオペランドを評価して、truthyな値があればその時点で評価を終える

console.log(false || true)//true

truthyな値: falsyな値を除くすべての値

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);

最後に


オプショナルチェーンを使ってコードを簡潔に書き、プロパティに値が入ってこない可能性があるならば積極的に使用してエラーを防ぎつつ読みやすいコードを書いていきたいです