TECH BOX

Technology blog from Web Engineer

この記事は最終更新日から6年以上経過しているため正確ではないかもしれません

今すぐ使えるES6以降での配列やオブジェクトの書き方

制作の現場でBabelやTypeScriptを使うということが結構当たり前になってきました。
そこで、最近のJavaScript(ES6以降)で利用頻度が高い実用性のある書き方を紹介します。

key:valueの省略

通常、オブジェクトはkey:valueで書きますが、ES6からは省略することができます。

// 通常
const foo = 1
const arr = {
  foo: foo
}

// ES6
const foo = 1
const arr = { foo } // => arr = { foo: 1 }
const arr2 = {
  foo,
  bar: 2
} // => arr2 = { foo: 1, bar: 2 }

keyとvalueが同一の変数名であれば省略することができます。

欲しいデータだけ取ってくる

ちょっと意味がわからないかもしれませんが、何らかのオブジェクトを受け取るときに、今までは一度すべて受け取ってからそれぞれ変数に展開していましたが、欲しいデータのみ特定の変数に展開できます。

実はimport文のimport { foo } from 'xxx'と似てるのです。

const data = {
  foo: 1,
  bar: 2,
  hoge: 3,
}

// 1. 変数名=取得元のkey名で統一する場合
const { foo, bar } = data // => foo = 1, bar = 2

// 2. 変数名を変更
const { hoge: goo } = data // => goo = 3

// 3. メソッドの戻り値の場合も同様
const func = () => {
  return {
    foo: 1,
    bar: 2
  }
}

const { foo } = func()

変数名とkeyが同じ場合は理解しやすいですが、何らかの理由で変数名を変更する場合は{ 渡す値 : 新しい変数名 }となります。
割と間違えがちなので注意が必要です(key:value形式で慣れてるから変数名が左に来るのが普通なので)。

なぜ、変更が必要かといえば複数のメソッド戻り値で同一のキー名が存在することもあるのでこういった回避方法があります。

配列/オブジェクトの操作

配列同士の結合する際、それぞれ適切なメソッドを選択する必要があったのですが、ES6以降の場合はスプレッド演算子が使えるので結合が直感的になりました。
※スプレッド演算子を使うとディープコピーになり、変更前の配列を参照しないので、配列前を変更しても結合した配列/オブジェクトには影響しません

まだすべてのブラウザが対応しているわけではないので、トランスパイルすると従来のロジックに変換されます。
(どのブラウザバージョンまで対応するかにもよりますが)

配列の結合

配列の場合は従来の方法だと、結合方法によってロジックが変わるので少々厄介でしたが、スプレッド演算子を使うと同じようにかけて便利。

const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]

// 1. すでに存在する配列に結合
arr1.push(...arr2) 
//=> [1, 2, 3, 4, 5, 6]
//=> 従来: Array.push.apply(Array)

// 2. 新たな配列に組み込む
const arr3 = [1, 2, 3, ...arr2] 
//=> [1, 2, 3, 4, 5, 6]
//=> 従来: [1, 2, 3].concat(Array)

// 3. 結合前の変数を変更しても影響はない
arr2[0] = 6
console.log(arr1) // [6, 5, 6]
console.log(arr2) // [1, 2, 3, 4, 5, 6]
console.log(arr3) // [1, 2, 3, 4, 5, 6]

配列内のオブジェクトは参照渡しになるので注意

配列内のオブジェクトは、参照が保たれるため結合前を変更してしまうと結合した方も変わってしまいます。

const arr1 = [
  { a: 1 },
  { b: 2 },
  5
]

const arr2 = [...arr1]

// 元の配列を更新
arr1[0].a = 5
arr1[2] = 1

console.log(arr1) // [{ a: 5 }, { b: 2 }, 1]
console.log(arr2) // [{ a: 5 }, { b: 2 }, 5]

オブジェクトの結合

const obj1 = {
  foo: 1,
  bar: 2
}

// 1. すでに存在するオブジェクトに結合
const obj2 = {
  ...obj1,
  hoge: 3
} // { foo: 1, bar: 2, hoge: 3}

// 2. 新たなオブジェクトを作成する
const obj3 = {
  hoge: 3
}

const obj = {...obj1, ...obj3} // { foo: 1, bar: 2, hoge: 3}

// 従来: objectの場合はすべてObject.assign({}, object1, object2)

// 3. 結合前のオブジェクトを変更しても影響はない
obj3.hoge = 5
obj3.hohoho = 3

console.log(obj2) // { foo: 1, bar: 2, hoge: 3}
console.log(obj3) // { hoge: 5, hohoho: 3 }
console.log(obj) // { foo: 1, bar: 2, hoge: 3 }

ディープコピーを作りたい場合

稀に元のオブジェクトを変更したくないけど一時的に中身を書き換えたい場合があります。

// 1. 失敗するやり方
const obj1 = { foo: 1 }
const obj2 = obj1
obj2.foo = 5

console.log(obj1) // { foo: 5 }
console.log(obj2) // { foo: 5 }

// 2. 成功する方法(従来: Object.assign({}, object))
const obj3 = { foo: 1 }
const obj4 = { ...obj3 }
obj4.foo = 5

console.log(obj3) // { foo: 1 }
console.log(obj4) // { foo: 5 }

記法に慣れるまでは気持ち悪いものもありますが(key:valueの省略とか)、今すぐ実践でも使えるので試してみてください。
もちろん、BabelやTypeScriptを使って書いてトランスパイルする前提ですが。