JavaScript 分割代入講座


JavaScript 分割代入講座

こんにちは、フロントエンド初心者です。
JavaScript には ES2015(ES6)から"分割代入(Destructuring Assignment)"
と呼ばれる機能が実装されました。
簡単に言うと、「代入の文を完結に書けるやり方」と言って良いと思います。
この機能は必ずしも取り入れなくてもコードは動きます。
しかし導入することでコード量は大幅に削減され、
見通しの良いスッキリしたコードになることは間違いありません。

現代の React 開発などでは、当たり前のように分割代入で
記述されているサンプルコードもよく目にしますので、
是非この記事で分割代入に慣れておきましょう。

分割代入はAirbnbの提供する JavaScript スタイルガイドでも推奨されています。

基本

“分割” は “破壊的” を意味しません
これは、項目を変数にコピーすることによって “非構造化(destructurizes)” するため、“分割代入(destructuring assignment)” と呼ばれています。 配列自体は変更されません。

分割代入の元の配列やオブジェクトはこの操作によって影響を受けることはありません。

配列

const [va1,var2,var3] = 配列
のように記述することで配列の中に入っている要素を
左辺の変数に分配していく形になります。
代入先の変数名はなんでもOKです。

// スマートじゃない書き方
const foods = ["🍣","🍖","🍕"];
const sushi = foods[0]
const meat = foods[1]
const pizza = foods[2]

// 分割代入の書き方
const animals = ["🐱","🐶","🐻"];
const [cat, dog, bear] = animals;
const [neko, inu, kuma] = animals; // OK

オブジェクト

const {va1,var2,var3} = オブジェクト
のように中括弧を使う点に注意しましょう。
また、代入先の変数名はプロパティ値と一致していなければいけないことに注意しましょう。
プロパティ値と異なる名前で代入する方法は後述します。

// スマートじゃない書き方
const foods = { 
  sushi: "🍣",
  meat: "🍖",
  pizza: "🍕" 
};

const sushi = foods['sushi']
const meat = foods['meat']
const pizza = foods['pizza']

// 分割代入の書き方
const animals = {
  cat: "🐱",                
  dog: "🐶", 
  bear: "🐻"
};

const { cat, dog, bear } = animals;
// 以下はNG。
// const { neko, inu, kuma } = animals;

応用編 - こんな時はどうすれば?

オブジェクトのプロパティ値と異なる名前で分割代入したい

オブジェクトの基本構文の通り、デフォルトではプロパティ値と同じ値でないと
分割代入ができません、でも違う名前で保存したい。そんな時。

const animals = {
  cat: "🐱",                
  dog: "🐶", 
  bear: "🐻"
};

// こんな書き方になる、可読性は低い。
const { cat: neko, dog: inu, bear: kuma } = animals;
console.log(neko,inu,kuma) // => "🐱","🐶","🐻"

左辺の変数が右辺の配列要素(オブジェクトプロパティ)より多い場合

エラーにはなりませんが、右辺の要素数で足りない分はundifinedとなります。

const animals = ["🐱","🐶","🐻"]

// エラーにはならない
const [cat,dog,bear,rabbit] = animals;
console.log(cat,dog,bear,rabbit) // => "🐱" "🐶" "🐻" undefined

左辺の変数が右辺の配列要素(オブジェクトプロパティ)より少ない場合

溢れる分を無視したい

この書き方で無視されて、左辺に存在する変数の数までを代入します。

// ウサギと豚が要らない!
const animals = ["🐱","🐶","🐻","🐰","🐷"];
// これでOK。
const [cat, dog, bear] = animals;
console.log(cat,dog,bear); // => "🐱","🐶","🐻"

溢れる分は最後の変数にまとめたい

スプレッド構文を使います。
なお、スプレッド構文でまとめられるのは最後の複数要素です。
間にスプレッド構文を使うと
「Uncaught SyntaxError: Rest element must be last element」
と怒られます。

// 熊とウサギと豚はまとめたい!
const animals = ["🐱","🐶","🐻","🐰","🐷"];
// これでOK。
const [cat, dog, ...other] = animals;
console.log(cat,dog,other); // => "🐱" "🐶" ["🐻", "🐰", "🐷"]

// これはNG。
const [cat, ...other, pig] = animals;

右辺の配列要素の最初の部分だけ要らない

カンマで左辺を区切ることにより、最初の要素を無視することができます。

// 猫と犬は要らない!
const animals = ["🐱","🐶","🐻","🐰","🐷"];
// これでOK。
const [,,bear,rabbit,pig] = animals;

左辺の変数にデフォルト値を用意したい

オブジェクトで、もし右辺のプロパティの中に該当するものがなかった場合に備えて
デフォルト値を用意しておくことができます。
例えば、右辺にユーザ情報のオブジェクトがくる場合で、プロフィール画像を設定している
ユーザとそうでないユーザがいるケースなどで結構使う気がします。

const animals = {
  cat: "🐱",                
  dog: "🐶", 
  bear: "🐻"
};

// animalsにはfoxはいないので左辺のデフォルト値が適用される
const { cat, dog, fox = "🦊" } = animals; 
console.log(cat, dog, fox); // => "🐱" "🐶" "🦊"

まとめ

さっと書けるとかっこいいので是非とも習得したいと思います。

最近見るのは、ReactのPropsをpropsという風に受け取らず
{username, description, children}などにして
以降のコードでprops.usernameといちいち書かずに
usernameと直接propsの名前にアクセスできるやり方です。

初見だと理解し辛いところがあるので、慣れておきましょう!

参考

https://ja.javascript.info/destructuring-assignment
https://qiita.com/uto-usui/items/a9d17447fe81c17c41fa
https://qiita.com/amamamaou/items/1ec21316b8bf05ba9c34