【JS】オブジェクト省略記法の使い方とOptionalChainingと併用できない話
こんにちは!久しぶりにjsの記事を書くMizutani(@sirycity)です。ブログにJavaScriptって入ってるのにね。
今回はjsの記法についての細かい話です。
オブジェクト省略記法とは
まずは普通の文法。人物一覧から名前だけを抜き出してみます。
const people = [
{name: {last: 'かわむら', first: 'たかし' }, age: 73 },
{name: {last: 'おおむら', first: 'ひであき' }, age: 61 },
{name: {last: 'よこい', first: 'としあき' }, age: 60 },
]
const names = people.map(person => {
const first = person.name.first
return first
})
console.log(names)
// ['たかし', 'ひであき', 'としあき']
ちょっとわざと丁寧に書いてるけどこんなかんじ。名前だけが抜け出せました!
説明しやすくするためにここからmapの中の処理だけを抜き出してみます。
const first = person.name.first
return first
ごく簡単な処理です。person(人物)の名前(name)の下の名前(first)。そのまんまですね。
ここからオブジェクト省略記法の話なんですが、JavaScriptは変数名とオブジェクトのキー名が同じ場合省略できるって仕様があり、こんな風に書けたりします。
const {first} = person.name
return first
さらに省略するとこう!
const {name: {first}} = person
return first
これを最初の文に入れるとこう。
const names = people.map(person => {
const {
name: { first },
} = person
return first
})
さらに省略する箇所をアロー関数の前に持ってくるとこう!この形の方がきれいだね。僕もよくこの書き方する。
const names = people.map(({ name: { first } }) => first)
この書き方はスマートなだけじゃなくて、変数の命名を省略できるのも便利だね。今回で言うところのperson
。今回は配列名がpeopleっていう単純な英単語だからいいけど、配列名が難しい単語だとこの部分の命名で迷ったりするし、そこの過程を省略できるのが良いですね。
オブジェクト省略記法については一旦ここまで。
OptionalChainingとは
次にOptionalChainingについてです。すっごい簡単に説明すると不明なデータを参照して起きるエラーを防ぐ機能みたいな感じです。
不明なデータについて。例えばこんな感じで正体不明の人が何人か混じっていたとします。
const people = [
{name: {last: 'かわむら', first: 'たかし' }, age: 73 },
{},
{name: {last: 'おおむら', first: 'ひであき' }, age: 61 },
{},
{name: {last: 'よこい', first: 'としあき' }, age: 60 },
]
この状態で名前だけを抜き出そうとすると…
const names = people.map(person => {
const first = person.name.first
return first
})
console.log(names)
// Error!
エラーになります。person(人物)の名前(name)の下の名前(first) を抜き出そうとするんだけど、そもそもperson(人物)の名前(name)が不明(undefined) なのでそいつの名前を参照しようとした時点でエラーになります。undefinedの下の名前(first) なんてないからね。
これをOptionalChainingにするとこう。
const names = people.map(person => {
const first = person.name?.first
return first
})
分かりやすく2行だけ抜き出すね。
const first = person.name?.first
return first
firstの直前に?
が付いてますね。これがOptionalChaining。
OptionalChainingが付くことで、何がなんでもfirstを参照してやる!(なので不明を参照するとエラー) からあったら参照してやる!(なので不明の場合は不明のまま) に変わります。なので結果は…
const names = people.map(person => {
const first = person.name?.first
return first
})
console.log(names)
// ['たかし', undefined, 'ひであき', undefined, 'としあき']
こんなかんじ。不明な人はundefinedのままになり、途中でエラーは起きないです。
NullishCoalescingとの合わせ技
余談ですがOptionalChainingはNullishCoalescingと組み合わせることもでき、中々面白いことができます。
こうやって書くと…
person.name?.first ?? '匿名さん'
こんな感じになります。
console.log(names)
// ['たかし', '匿名さん', 'ひであき', '匿名さん', 'としあき']
この方が見た目きれいだね!NullishCoalescingは奥が深いのでそのうち個別に記事書きたいです。
オブジェクト省略記法とOptionalChainingは併用できない
だいぶ前置きが長くなりましたが、一応今回の本題です。オブジェクト省略記法とOptionalChainingは併用できないケースが多いです 。
言い方を変えると、不明なデータが入る可能性がある場合はオブジェクト省略記法は使わないようにしよう! ってことです。
ためしに匿名さんのいるデータで省略記法を使うと…
const people = [
{name: {last: 'かわむら', first: 'たかし' }, age: 73 },
{},
{name: {last: 'おおむら', first: 'ひであき' }, age: 61 },
{},
{name: {last: 'よこい', first: 'としあき' }, age: 60 },
]
const names = people.map(({ name: { first } }) => first)
console.log(names)
// Error!
エラーになります。これはまあ当たり前ですね。アロー関数の左辺でfirstを参照してるけどfirstが無いデータがあるのでそこでエラーが起きます。
んで、オブジェクト省略記法バージョンのOptionalChaining みたいな文法はJavaScriptには無いです。あったら便利だけどね。しょうがないね。
結論
オブジェクト省略記法はスマートだけどOptionalChainingと組み合わせられないケースも多いよ!不明なデータが入ってくる時は注意!
すごい細かい仕様の話でした。以上!