JavaScriptの分割代入でそれぞれのデータを抽出して使用する


ES2015から使えるようになった分割代入ですが、皆様使ってますか?
使ってみると便利な書き方なのですが、私は最初にコードをみた時は「???」でした。
(最初は分割代入という言葉すら知りませんでした、、)
今回は私のように「分割代入って何?」という方向けに簡単な使い方をまとめてみました。

分割代入とは

一言でいうと、分割代入とはデータを抽出する非常に便利な方法です。
もっと詳しくいうと、オブジェクトや配列などのデータ構造から値・プロパティを(文字通り!)分割して、別個の変数に代入する事を可能にする方法です。
それをふまえた上で、分割代入の使い方をそれぞれみていきます。

配列の分割代入

配列から各要素を取り出して変数に代入していきます。

ES2015以前では、要素ごとに1つの変数を記述する必要がありました。
対して分割代入を利用すれば変数宣言することなく1つの式として簡潔に書くことができます。
また(...)を使用して、残りの配列をまとめたり、関数の戻り値(配列)に分割代入を利用することもできます。

const monsters = ['フシギダネ', 'ヒトカゲ', 'ゼニガメ']

// 配列の値をそれぞれ変数に代入する
const x0 = monsters[0]
const x1 = monsters[1]
const x2 = monsters[2]
console.log(x0, x1, x2) // フシギダネ ヒトカゲ ゼニガメ 

// 上記を分割代入で再現
const [y0, y1, y2] = monsters
console.log(y0, y1, y2) // フシギダネ ヒトカゲ ゼニガメ 

// ...を利用して残りの配列を変数に代入
const [z0, ...rest] = monsters
console.log(z0) // フシギダネ
console.log(rest) // ['ヒトカゲ', 'ゼニガメ']

// 関数の戻り値(配列)に分割代入を利用
const returnMonsters = (): string[] => monsters
const [w0, w1, w2] = returnMonsters()
console.log(w0, w1, w2) // フシギダネ ヒトカゲ ゼニガメ

オブジェクトの分割代入(変数)

オブジェクトから任意のプロパティだけを抽出して変数に代入していきます。

{x, y, z, ...}に抽出したいプロパティのキーを入れる事でオブジェクトから任意のデータを取得できます。そのキーと同名の変数にデータが代入されます。
(キー名とは異なる名前の変数名にすることも可能です {キー名: 新しい変数名})
また、配列と同様に残りをまとめたり、関数の戻り値に対しても分割代入を使用できます。

const husigidane = {
  no: 1,
  name: 'フシギダネ',
  isMegaEvolution: false,
  types: ['くさ', 'どく'],
  abilities: ['しんりょく'],
  hiddenAbilities: ['ようりょくそ'],
  stats: {
    hp: 45,
    attack: 49,
    defence: 49,
    spAttack: 65,
    spDefence: 65,
    speed: 45
  }
}

// オブジェクトのプロパティをそれぞれ変数に代入
const no = husigidane.no
const types = husigidane.types
console.log(no, types) // 1 ['くさ', 'どく']

// 上記を分割代入で再現
const {abilities, hiddenAbilities} = husigidane
console.log(abilities, hiddenAbilities) // ['しんりょく'] ['ようりょくそ']

// 抽出したキー名とは別の変数名とする
const {name: monsterName} = husigidane
console.log(monsterName) // フシギダネ

// ネストしたオブジェクトのプロパティ
const {isMegaEvolution, stats: {attack: attackValue}} = husigidane
console.log(isMegaEvolution, attackValue) // false 49

オブジェクトの分割代入(引数)

オブジェクトをとる引数に分割代入を使用することもできます。

分割代入を使用することで、引数で受け取ったオブジェクトから不必要なプロパティを触ることなく処理ができますし、どのプロパティを関数で使うか見通しが良くなります。


type LogMonster = {
  name: string,
  types: string[],
  stats: {
    attack: number,
    defence: number
  }
}

const hitokage = {
  no: 4,
  name: "ヒトカゲ",
  types: ["ほのお"],
  abilities: ["もうか"],
  stats: {
    hp: 39,
    attack: 52,
    defence: 43,
    spAttack: 60,
    spDefence: 50,
    speed: 65
  }
}

// 引数にオブジェクトをとる関数
const logMonsterAttack = (monster: LogMonster): void => {
  const name = monster.name
  const types = monster.types
  const spAttack = monster.stats.attack
  console.log(name, types, spAttack)
}
logMonsterAttack(hitokage) // ヒトカゲ ["ほのお"] 52

// 上記を分割代入で再現してみる
const logMonsterDefence = (
    {name, types, stats: {defence: defenceValue}}: LogMonster
  ): void => {
  console.log(name, types, defenceValue)
}
logMonsterDefence(hitokage) // ヒトカゲ ["ほのお"] 52

おわりに

{}がやたら多くて、最初は分割代入に対して読みづらさを感じてたのですが、簡単なコードを書いて検証することで理解が深まりました。
そこで今回忘れないためにもまとめてみました。
読んでくださった方々の理解に少しでも貢献できていたらと思います。

今回ご紹介させていただいた分割代入の使い方はまだまだ一部です。
もっと知りたい方はMDNの公式サイトをご覧になってください。