初めに
Optional_chaingについて学習した内容のoutput用記事です。
※内容に間違いなどがある場合はご指摘をよろしくお願いします。
Optional_chainingとは
MDNの公式ドキュメントには次のように書かれています。
接続されたオブジェクトチェーンの深くに位置するプロパティの値を、チェーン内の各参照が正しいかどうかを明示的に確認せずに読み込むことを可能にします。
「.」チェーンプロパティーと似ていますが、プロパティーの有無に関わらずエラーを出さずに調べたいプロパティーの値を読み込むことができます。言葉だけでは難しいので、早速使ってみることに。
Optional_chainingを使わない時の問題について
まず、「.」チェーンプロパティーを使うために、次のようなobjectを用意します。
const stores = {
bookStore: {
mon: { open: 10, close: 20 },
tue: { open: 11, close: 19 },
},
};
storesの中のbookStoreにはmonとtueがあり、それぞれのmonとtueにはopenとcloseの値が入っています。もし、このような構造を知らずに、外部の利用者がsunにもopenとcloseの値があると思い、値を取り出す場合を考えてみます。
console.log(stores.bookStore.sun.open); //エラーになる
このように書くと次のようなエラーが出ます。
今度はif文を使ってstores.bookStore.sun.openが存在すればという条件を付けてみます。
if (stores.bookStore.sun.open) console.log(stores.bookStore.sun.open); //エラーになる。
同じようなエラーになります。
これはsotresの一番深い階層のopenプロパテーの有無を判定するためには、さらにその前のsunプロパティーが存在するかどうかを判定する必要があるからです。
なので&&演算子を使って次のように書き直す必要があります。
if (stores.bookStore && stores.bookStore.sun)
console.log(sotres.bookStore.sun.open); //エラー画面が表示されない
このようにするとエラーにはなりませんが、書き方的には長いです。1つのプロパティーだけならいいんですが、複数ある場合は大変です。さらに階層が深くなれば深くなるほど、if文は長くなるので尚更です。
Optional chainingを使ってみる
sunにopenプロパティーがあればopenの値をコンソールに表示したい場合、optional chainingを使うと以下のように記述できます。
console.log(stores.bookStore.sun?.open);
結果は以下の通り。
存在しないので、undefinedと表示されます。「.」メソッドの前に「?」を付けるだけなので、とても簡単です。
もちろん、sunが存在するかどうかも分からない場合にはsunの前に「?.」を付けます。
console.log(stores.bookStore?.sun?.open);
monからsunまでの曜日が入っている箱をdaysに格納し、for of文を使ってコンソールに表示してみます。
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、またはそのプロパティーの値を返してくれます。
objectのメソッドが存在しない場合にも対応できます。
//中略
console.log(stores.add?.(2, 5));
sotresオブジェクトにはaddというメソッドは存在しないので「?.」を使うと次のようにundefinedを返してくれます。
ここでundefinedと表示させたくないので、前回学んだ(??)合体演算子を使ってみます。
console.log(stores.add?.(2, 5) ?? "存在しないメソッドです。");
stores.add?.(2, 5)がundefinedで評価されず、"存在しないメソットです。"が表示されます。
optional chainingを使うと条件分岐を書く必要が無くなります。
次のような場面でnameが存在するかしないかによってnameの値を表示するもしくは"木は存在しません。"という処理を簡潔に書くことができます。
const trees = [{ name: "ヒノキ" }, { numbers: 3 }];
console.log(trees[0]?.name ?? "木は存在しません。");
同じ処理をoptional chainingを使わない場合だと以下のように記述しなければなりません。
if (trees.length > 0) console.log(trees[0].name);
else console.log("木は存在しません。");
可読性も悪くなるし、記述も長くなってしまいます。このようにOptional Chainingはとても便利な機能なので、これからも使ってみたいと思いました。