【Javascript】Optional_chaining（追加的な？選択的な？連鎖）について

# 初めに
Optional_chaingについて学習した内容のoutput用記事です。

※内容に間違いなどがある場合はご指摘をよろしくお願いします。

# Optional_chainingとは
MDNの公式ドキュメントには次のように書かれています。
>接続されたオブジェクトチェーンの深くに位置するプロパティの値を、チェーン内の各参照が正しいかどうかを明示的に確認せずに読み込むことを可能にします。

「.」チェーンプロパティーと似ていますが、プロパティーの有無に関わらずエラーを出さずに調べたいプロパティーの値を読み込むことができます。言葉だけでは難しいので、早速使ってみることに。

# Optional_chainingを使わない時の問題について
まず、「.」チェーンプロパティーを使うために、次のようなobjectを用意します。

```javascript
  const stores = {
        bookStore: {
          mon: { open: 10, close: 20 },
          tue: { open: 11, close: 19 },
        },
      };
```
storesの中のbookStoreにはmonとtueがあり、それぞれのmonとtueにはopenとcloseの値が入っています。もし、このような構造を知らずに、外部の利用者がsunにもopenとcloseの値があると思い、値を取り出す場合を考えてみます。

```javascript
console.log(stores.bookStore.sun.open);    //エラーになる
```
このように書くと次のようなエラーが出ます。
![スクリーンショット 2021-05-30 8.55.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/4be1f8f6-0464-5652-5513-db24dd978641.png)
今度はif文を使ってstores.bookStore.sun.openが存在すればという条件を付けてみます。

```javascript
if (stores.bookStore.sun.open) console.log(stores.bookStore.sun.open);    //エラーになる。
```
同じようなエラーになります。
![スクリーンショット 2021-05-30 8.57.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/3339579c-32a2-1a08-757d-828d0a9e3bb7.png)
これは<b>sotresの一番深い階層のopenプロパテーの有無を判定するためには、さらにその前のsunプロパティーが存在するかどうかを判定する必要があるからです。</b>
なので&&演算子を使って次のように書き直す必要があります。

```javascript
if (stores.bookStore && stores.bookStore.sun)

    console.log(sotres.bookStore.sun.open);  //エラー画面が表示されない
```
このようにするとエラーにはなりませんが、書き方的には長いです。1つのプロパティーだけならいいんですが、複数ある場合は大変です。さらに階層が深くなれば深くなるほど、if文は長くなるので尚更です。

# Optional chainingを使ってみる
sunにopenプロパティーがあればopenの値をコンソールに表示したい場合、optional chainingを使うと以下のように記述できます。

```javascript
console.log(stores.bookStore.sun?.open);
```
結果は以下の通り。
![スクリーンショット 2021-05-30 9.06.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/e4b6bfa4-e5cd-7fef-d607-25a32325a7cc.png)
存在しないので、undefinedと表示されます。「.」メソッドの前に「?」を付けるだけなので、とても簡単です。
もちろん、sunが存在するかどうかも分からない場合にはsunの前に「?.」を付けます。

```javascript
console.log(stores.bookStore?.sun?.open);
```
結果は同じくundefinedです。
![スクリーンショット 2021-05-30 9.06.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/e4b6bfa4-e5cd-7fef-d607-25a32325a7cc.png)

monからsunまでの曜日が入っている箱をdaysに格納し、for of文を使ってコンソールに表示してみます。

```javascript
const stores = {
        bookStore: {
          mon: { open: 10, close: 20 },
          tue: { open: 11, close: 19 },
        },
      };

//以下を追記
const days = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];

for (const day of days) {
     const open = stores.bookStore[day]?.open;
     console.log(`${day}: ${open}時に開きます。`);
     }
```
「?.」を使うとbookStore[day]にopenプロパティーが存在するかどうかでundefined、またはそのプロパティーの値を返してくれます。
![スクリーンショット 2021-05-30 9.21.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/ccb6e989-a476-5ade-ff3c-e449db794fce.png)

objectのメソッドが存在しない場合にも対応できます。

```javascript
//中略
console.log(stores.add?.(2, 5));
```
sotresオブジェクトにはaddというメソッドは存在しないので「?.」を使うと次のようにundefinedを返してくれます。
![スクリーンショット 2021-05-30 9.06.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/e4b6bfa4-e5cd-7fef-d607-25a32325a7cc.png)

ここでundefinedと表示させたくないので、前回学んだ(??)合体演算子を使ってみます。

https://qiita.com/redrabbit1104/items/3069c7e0b84e9b665610

```javascript
console.log(stores.add?.(2, 5) ?? "存在しないメソッドです。");
```
stores.add?.(2, 5)がundefinedで評価されず、"存在しないメソットです。"が表示されます。
![スクリーンショット 2021-05-30 9.37.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/3279ca6b-b0c1-0874-2e3f-a1f109b82b02.png)

optional chainingを使うと条件分岐を書く必要が無くなります。
次のような場面でnameが存在するかしないかによってnameの値を表示するもしくは"木は存在しません。"という処理を簡潔に書くことができます。

```javascript
const trees = [{ name: "ヒノキ" }, { numbers: 3 }];

console.log(trees[0]?.name ?? "木は存在しません。");
```
![スクリーンショット 2021-05-30 9.50.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/19756fe1-b3df-d2a9-4d8e-6d9e5c63e7db.png)

同じ処理をoptional chainingを使わない場合だと以下のように記述しなければなりません。

```javascript
if (trees.length > 0) console.log(trees[0].name);
else console.log("木は存在しません。");
```
可読性も悪くなるし、記述も長くなってしまいます。このようにOptional Chainingはとても便利な機能なので、これからも使ってみたいと思いました。

# 参考サイト
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining