JavaScriptのスプレッド構文を使うべき5つの用途

スプレッド構文とは

JavaScriptで配列やオブジェクトを展開して要素を取り出すための構文です。

3つのドット ... を使い、配列やオブジェクトの要素を簡単にコピーしたり、引数として渡したりできます。

スプレッド構文には以下の5つの用途に利用できます。

1. 配列の追加

昔は配列のconcat()が使用されていましたが、現在はスプレッド構文を使えば配列を展開して、以下のようにシンプルに記述できます。

JavaScript
const arr1 = [1, 2, 3]
const arr2 = arr1.concat([4, 5])
console.log(arr2)
// [1, 2, 3, 4, 5]
JavaScript
const arr1 = [1, 2, 3]
const arr2 = [...arr1, 4, 5]
console.log(arr2)
// [1, 2, 3, 4, 5]

前後に追加したい場合もこのようにシンプルに書けます。

JavaScript
const arr1 = [1, 2]
const arr2 = [5, 6]
const result = [...arr1, 3, 4, ...arr2]
console.log(result)
// [1, 2, 3, 4, 5, 6]

もし、concatの場合は以下のようになるため可読性が低下します。

JavaScript
const arr1 = [1, 2]
const arr2 = [5, 6]
const result = arr1.concat(3, 4).concat(arr2)
console.log(result)
// [1, 2, 3, 4, 5, 6]

配列の追加にconcat()を使うのは古い書き方なのでやめましょう。

concatは「concatenate(連結する)」 の略ですが、日本人には聞き慣れていない英単語なので、「comcat」や「concut」のようなスペルミスも発生しやすいです。

2. 配列のコピー

配列はそのままコピーすると元の配列の値を参照してしまいます。

JavaScript
const original = [1, 2, 3]
const copy = original

copy[0] = 99
console.log(original)  // [99, 2, 3]

そのため、昔は参照を避けるため、slice()やArray.from()がよく利用されていました。

JavaScript
const original = [1, 2, 3]
const copy = original.slice()
// Array.from(original) も可

copy[0] = 99
console.log(original)  // [1, 2, 3]

しかし、現在はスプレッド構文を使えば同じことができます。

JavaScript
const original = [1, 2, 3]
const copy = [...original]
copy[0] = 99
console.log(original)  // [1, 2, 3]

配列のコピーにslice()やArray.from()を使うのは古い書き方なのでやめましょう。

3. 関数の引数としての展開

昔は関数の引数として展開する場合はapply()が使用されていました。

JavaScript
const numbers = [4, 5, 6]
const result = Math.max.apply(null, numbers)
console.log(result) // 6

しかし、現在はスプレッド構文を使えば同じことができます。

JavaScript
const numbers = [4, 5, 6]
const result = Math.max(...numbers)
console.log(result) // 6

関数の引数としての展開にapply()を使うのは古い書き方なのでやめましょう。

4. オブジェクトの展開

オブジェクトのプロパティを展開して、新しいオブジェクトを作成するのにも使えます。

JavaScript
const obj1 = { a: 1, b: 2 }
const obj2 = { ...obj1, c: 3 }
console.log(obj2)
// { a: 1, b: 2, c: 3 }

昔はObject.assign()などが使用されていたので、オブジェクトの展開のコードの可読性が悪かったです。

JavaScript
const obj1 = { a: 1, b: 2 }
const obj2 = Object.assign({}, obj1, { c: 3 })
console.log(obj2)
// { a: 1, b: 2, c: 3 }

ちなみに、スプレッド構文をオブジェクトのコピーに使用されているケースもありますが、「シャローコピー」という浅いコピーなので、ネストされたオブジェクトや配列の内部まではコピーされません。

JavaScript
const original = { a: 1, b: { c: 2 } }
const copy = { ...original }
copy.b.c = 99
console.log(original.b.c) // 99

オブジェクトのコピーにはスプレッド構文ではなく structuredClone() を使用してください。

structuredClone()であればディープコピー(深いコピー)なので、元の配列が参照により変更されることはないです。

JavaScript
const original = { a: 1, b: { c: 2 } }
const copy = structuredClone(original)
copy.b.c = 99
console.log(original.b.c) // 2

5. 文字列の配列化

昔は文字列を文字単位の配列にするにはsplit('')が良く使われていました。

JavaScriptでは文字を直接反転させるメソッドがないため、文字単位に配列にしてreverse()で反転させるためによく使われていました。

JavaScript
const str = 'ABC'
const reverseStr = str.split('').reverse().join('')
console.log(reverseStr)
// 'CBA'

スプレッド構文を使えば文字単位に分割できるので、split('')を使わずに済みます。

JavaScript
const str = 'ABC'
const reverseStr = [...str].reverse().join('')
console.log(reverseStr)
// 'CBA'

まとめ

スプレッド構文は以下の5つの用途に使えます。

  1. 配列の追加
  2. 配列のコピー
  3. 関数の引数としての展開
  4. オブジェクトの展開
  5. 文字列の配列化

スプレッド構文だけでできるのに、concat()などのメソッドを使用するとコードの可読性の低下や、メソッドのスペルミスによるバグの発生などにつながります。

特に理由がなければ、これら5つの用途にはスプレッド構文を使うようにしましょう。