JavaScriptのドット3つ(…)とは?スプレッド構文を徹底解説

1. はじめに

JavaScriptを学んでいると、...(ドット3つ)という記号を目にすることがあります。これは「スプレッド構文(Spread Syntax)」または「レスト構文(Rest Syntax)」と呼ばれ、配列やオブジェクトの操作を簡潔に記述できる便利な機能です。

本記事では、JavaScriptのスプレッド構文について、初心者にも分かりやすく解説します。また、実践者の方々の復習にも役立つよう、具体例を交えながら説明していきます。

2. スプレッド構文とは?

2.1 スプレッド構文の基本

スプレッド構文(Spread Syntax)は、配列やオブジェクトを展開(分割)するための構文です。

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

このように、...arr1を使用することでarr1の要素を展開し、新しい配列に追加できます。

2.2 配列のコピーと結合

スプレッド構文は、配列のコピーや結合にも使用できます。

const originalArray = [1, 2, 3];
const copyArray = [...originalArray];
console.log(copyArray); // [1, 2, 3]

const mergedArray = [...originalArray, 4, 5, 6];
console.log(mergedArray); // [1, 2, 3, 4, 5, 6]

スプレッド構文を使うことで、元の配列を変更せずに新しい配列を作成できます。

2.3 オブジェクトの展開

スプレッド構文はオブジェクトにも適用できます。

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

オブジェクトの展開を使えば、プロパティの追加や上書きも簡単に行えます。

3. スプレッド構文の活用例

3.1 配列の要素を関数の引数として渡す

function sum(a, b, c) {
  return a + b + c;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers)); // 6

スプレッド構文を使用すると、配列の要素を個々の引数として渡せます。

3.2 配列の最大値を求める

const numbers = [10, 20, 5, 8];
console.log(Math.max(...numbers)); // 20

Math.max()にスプレッド構文を使うことで、配列の最大値を簡単に求められます。

3.3 オブジェクトのマージ

const obj1 = { name: "Alice", age: 25 };
const obj2 = { job: "Engineer", city: "Tokyo" };
const mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj); // { name: "Alice", age: 25, job: "Engineer", city: "Tokyo" }

スプレッド構文でオブジェクトを結合すれば、元のオブジェクトを変更せずに新しいオブジェクトを作成できます。

4. ありがちなミス

4.1 配列のコピーと参照の違い

スプレッド構文で配列をコピーする場合、ネストされたオブジェクトは参照のままとなるので注意が必要です。

const originalArray = [{ a: 1 }, { b: 2 }];
const copyArray = [...originalArray];
copyArray[0].a = 99;
console.log(originalArray[0].a); // 99

オブジェクトの完全なコピーにはJSON.parse(JSON.stringify(obj))structuredClone(obj)を使用しましょう。

4.2 間違った使い方

const numbers = [1, 2, 3];
console.log(...numbers); // SyntaxError

スプレッド構文は配列を展開できますが、単独では使用できません。

5. 実践的な利用例

5.1 Reactのコンポーネントでの活用

スプレッド構文は、Reactのコンポーネントにプロパティ(props)を渡す際に便利です。

const user = { name: "Alice", age: 25 };

function UserProfile(props) {
  return <div>{props.name} ({props.age})</div>;
}

function App() {
  return <UserProfile {...user} />;
}

このように、...userを使うことでuserオブジェクトの各プロパティをUserProfileコンポーネントに渡せます。

5.2 フォームデータの更新

const user = { name: "Alice", age: 25 };
const updatedUser = { ...user, age: 26 };
console.log(updatedUser); // { name: "Alice", age: 26 }

6. エラーメッセージの例

6.1 スプレッド構文の誤用

const obj = null;
const newObj = { ...obj }; // TypeError: Cannot convert null to object

オブジェクトの展開時、nullundefinedを展開しようとするとエラーが発生します。

7. スプレッド構文とレスト構文の違い

7.1 レスト構文とは?

スプレッド構文と似た記法として、レスト構文(Rest Syntax)があります。レスト構文は、関数の引数をまとめる際に使用します。

function sum(...args) {
  return args.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10

8. まとめ

JavaScriptの...(ドット3つ)は、スプレッド構文とレスト構文の2つの用途があります。

9. 参考リンク