分割代入で必要な値だけ取り出す
このレッスンで分かること
- 引数の位置で開くと、関数の 1 行目が「この関数が使う値の一覧」になります
- 途中の階層が無いところで止まらないよう、階層ごとに受け皿を置きます
関数の 1 行目を見ても、何を使うのか分からない
入門では const { name } = profile; のように、関数の中で開く形を覚えました。実践では置き場所を一段前に動かします。関数の中ではなく、引数の位置に書きます。
JavaScript
// 中で開く。呼び出す側からは何を使うのか見えない
function renderProfile(profile) {
const name = profile.name;
const mail = profile.contact.email;
return name + " " + mail;
}
// 入口で開く。1 行目が使う値の一覧になる
function renderProfile({ name, contact }) {
return name + " " + contact.email;
}書く文字数はほとんど変わりませんが、読み手にとっての意味が違います。後者は 1 行目を見ただけで「この関数は name と contact しか触らない」と分かります。プロフィールがキーを 7 つ 8 つ持つようになった今、これは小さくない差です。
呼び出す側にも効きます。名前付きで渡す形になるので、引数の順番を覚える必要がなくなります。引数が 3 つを超えたらオブジェクト 1 つにまとめる、という設計判断がここから生まれます。
途中の階層が無いと、そこで止まる
入れ子を開くときに必ず踏む罠がここです。
JavaScript
const profile = { name: "山田 太郎" };
const { contact: { email } } = profile;
// TypeError Cannot read properties of undefinedundefined の中の email を読もうとしたので止まりました。防ぎかたは、開こうとしている階層に既定値を付けることです。
JavaScript
const { contact: { email = "未登録" } = {} } = profile;
console.log(email); // 未登録contact が無ければ空のオブジェクトを代わりに開くので、その中の email も無く、既定値が採用されます。階層ごとに受け皿を置く、と覚えてください。引数そのものが渡されないかもしれないなら、いちばん外側にも同じことをします。
JavaScript
function renderProfile({ name = "名無し", contact: { email = "未登録" } = {} } = {}) {
return name + " " + email;
}
console.log(renderProfile()); // 名無し 未登録名前を付け替える、配列は位置で受ける
取り出しながら改名もできます。contact: { email: mail = "未登録" } は「contact の中の email を mail という名前で受け取り、無ければ既定値」と読みます。左がキー、真ん中が変数名、後ろが既定値の順です。
配列が入っているキーは、その位置に [] を書きます。名前ではなく位置で対応するので、先頭の 1 件だけ欲しいなら 1 つだけ書けば足ります。
| 書きかた | 何が起きるか |
|---|---|
{ name } | name という変数ができる |
{ name: owner } | owner ができる。name はできない |
{ name = "名無し" } | 値が undefined のときだけ既定値を使う |
{ contact: { email } } | email だけができる。contact はできない |
{ links: [first] } | 配列の 0 番目が first になる |
{ ... } = {} | 引数そのものが無いときの受け皿 |
既定値が使われるのは値が undefined のときだけです。null や 0 や空文字はそのまま採用されるので、null も倒したいなら開いたあとに ?? を書きます。
よくある間違い
- 開いた親の変数を使ってしまう —
{ contact: { email } }は「開く指示」であって変数宣言ではないので、contactは存在しません。親も使いたいなら{ contact, contact: { email } }と両方書きます - 受け皿を 1 か所しか置かない — 引数全体に
= {}があっても、contactに付いていなければ足りません。引数が渡されていれば外側の既定値は使われず、undefinedのcontactを開いて落ちます - 付け替えと既定値の順番を逆に書く —
{ name = "名無し": owner }は構文エラーです。キー、変数名、既定値の順に並べます
要件
- 関数名は describeWork。引数は作品オブジェクト 1 つで、引数そのものが省略されることもある
- 引数の位置で分割代入する。title の既定値は 無題、year の既定値は 年不明
- stats の中の views を viewCount という名前で取り出す。既定値は 0 で、stats 自体が無くても動くようにする
- tags の先頭を mainTag として取り出す。既定値は 未分類 で、tags 自体が無くても動くようにする
- 戻り値は { label, viewCount, mainTag } のオブジェクト。label は タイトル (年) の形にする
入出力例
describeWork({"id":1,"stats":{"likes":8,"views":120},"tags":["HTML","CSS"],"title":"プロフィールサイト","year":2026}) → {"label":"プロフィールサイト (2026)","mainTag":"HTML","viewCount":120}
describeWork({"id":5,"title":"学習ログ","year":2026}) → {"label":"学習ログ (2026)","mainTag":"未分類","viewCount":0}
describeWork({}) → {"label":"無題 (年不明)","mainTag":"未分類","viewCount":0}
describeWork() → {"label":"無題 (年不明)","mainTag":"未分類","viewCount":0}
describeWork({"id":2,"stats":{"views":0},"tags":[],"title":"自己紹介カード","year":2025}) → {"label":"自己紹介カード (2025)","mainTag":"未分類","viewCount":0}