
スプレッド構文とは
JavaScriptで配列やオブジェクトを展開して要素を取り出すための構文です。
3つのドット ... を使い、配列やオブジェクトの要素を簡単にコピーしたり、引数として渡したりできます。
スプレッド構文には以下の5つの用途に利用できます。
1. 配列の追加
昔は配列のconcat()が使用されていましたが、現在はスプレッド構文を使えば配列を展開して、以下のようにシンプルに記述できます。
const arr1 = [1, 2, 3]
const arr2 = arr1.concat([4, 5])
console.log(arr2)
// [1, 2, 3, 4, 5]
const arr1 = [1, 2, 3]
const arr2 = [...arr1, 4, 5]
console.log(arr2)
// [1, 2, 3, 4, 5]
前後に追加したい場合もこのようにシンプルに書けます。
const arr1 = [1, 2]
const arr2 = [5, 6]
const result = [...arr1, 3, 4, ...arr2]
console.log(result)
// [1, 2, 3, 4, 5, 6]
もし、concatの場合は以下のようになるため可読性が低下します。
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. 配列のコピー
配列はそのままコピーすると元の配列の値を参照してしまいます。
const original = [1, 2, 3]
const copy = original
copy[0] = 99
console.log(original) // [99, 2, 3]
そのため、昔は参照を避けるため、slice()やArray.from()がよく利用されていました。
const original = [1, 2, 3]
const copy = original.slice()
// Array.from(original) も可
copy[0] = 99
console.log(original) // [1, 2, 3]
しかし、現在はスプレッド構文を使えば同じことができます。
const original = [1, 2, 3]
const copy = [...original]
copy[0] = 99
console.log(original) // [1, 2, 3]
配列のコピーにslice()やArray.from()を使うのは古い書き方なのでやめましょう。
3. 関数の引数としての展開
昔は関数の引数として展開する場合はapply()が使用されていました。
const numbers = [4, 5, 6]
const result = Math.max.apply(null, numbers)
console.log(result) // 6
しかし、現在はスプレッド構文を使えば同じことができます。
const numbers = [4, 5, 6]
const result = Math.max(...numbers)
console.log(result) // 6
関数の引数としての展開にapply()を使うのは古い書き方なのでやめましょう。
4. オブジェクトの展開
オブジェクトのプロパティを展開して、新しいオブジェクトを作成するのにも使えます。
const obj1 = { a: 1, b: 2 }
const obj2 = { ...obj1, c: 3 }
console.log(obj2)
// { a: 1, b: 2, c: 3 }
昔はObject.assign()などが使用されていたので、オブジェクトの展開のコードの可読性が悪かったです。
const obj1 = { a: 1, b: 2 }
const obj2 = Object.assign({}, obj1, { c: 3 })
console.log(obj2)
// { a: 1, b: 2, c: 3 }
ちなみに、スプレッド構文をオブジェクトのコピーに使用されているケースもありますが、「シャローコピー」という浅いコピーなので、ネストされたオブジェクトや配列の内部まではコピーされません。
const original = { a: 1, b: { c: 2 } }
const copy = { ...original }
copy.b.c = 99
console.log(original.b.c) // 99
オブジェクトのコピーにはスプレッド構文ではなく structuredClone() を使用してください。
structuredClone()であればディープコピー(深いコピー)なので、元の配列が参照により変更されることはないです。
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()で反転させるためによく使われていました。
const str = 'ABC'
const reverseStr = str.split('').reverse().join('')
console.log(reverseStr)
// 'CBA'
スプレッド構文を使えば文字単位に分割できるので、split('')を使わずに済みます。
const str = 'ABC'
const reverseStr = [...str].reverse().join('')
console.log(reverseStr)
// 'CBA'
まとめ
スプレッド構文は以下の5つの用途に使えます。
- 配列の追加
- 配列のコピー
- 関数の引数としての展開
- オブジェクトの展開
- 文字列の配列化
スプレッド構文だけでできるのに、concat()などのメソッドを使用するとコードの可読性の低下や、メソッドのスペルミスによるバグの発生などにつながります。
特に理由がなければ、これら5つの用途にはスプレッド構文を使うようにしましょう。