JavaScript

Object.assign()とスプレッド構文の違いを初心者向けに整理

JavaScriptでオブジェクトをコピー・結合するときに使うObject.assign()とスプレッド構文について、書き方や元のオブジェクトへの影響を実例で整理します。

この記事でわかること

  • Object.assign()は指定したオブジェクトへプロパティを追加・上書きするメソッドです。
  • スプレッド構文は新しいオブジェクトを作る書き方として利用できます。
  • どちらも基本的には浅いコピーであり、ネストしたオブジェクトの扱いには注意が必要です。
  • 元のオブジェクトを変更したくない場合は、スプレッド構文が意図を表しやすい選択肢になります。

Object.assign()とスプレッド構文は何が違うのか

どちらもオブジェクトのプロパティをコピー・結合できます。大きな違いは、Object.assign()が第1引数のtargetへ値を適用するのに対し、スプレッド構文は新しいオブジェクトを作る書き方として利用する点です。

たとえば、既存のオブジェクトへ設定を反映するならObject.assign()、元の値を残したまま更新後のオブジェクトを作るならスプレッド構文、というように考えると整理しやすくなります。

Object.assign()の基本的な使い方

基本構文はObject.assign(target, ...sources)です。sourceの列挙可能な自身のプロパティがtargetへコピーされ、同じプロパティ名がある場合は後から指定した値で上書きされます。

JavaScript
const defaults = { theme: "light", pageSize: 20 };
const options = { pageSize: 50 };

const settings = Object.assign(defaults, options);

console.log(settings);
// 期待される結果: { theme: "light", pageSize: 50 }
console.log(defaults);
// 期待される結果: { theme: "light", pageSize: 50 }

この例では、defaultsをtargetに指定しているため、defaults自体が変更されます。元のオブジェクトを変更したくない場合は、空のオブジェクトをtargetに指定します。

JavaScript
const user = { name: "Aki", role: "user" };
const updates = { role: "admin" };

const updatedUser = Object.assign({}, user, updates);

console.log(updatedUser);
// 期待される結果: { name: "Aki", role: "admin" }
console.log(user);
// 期待される結果: { name: "Aki", role: "user" }

スプレッド構文の基本的な使い方

オブジェクトのスプレッド構文は、{ ...source }のように記述します。プロパティを展開して、新しいオブジェクトを作成できます。複数のオブジェクトを展開した場合は、後に書いたオブジェクトの値が優先されます。

JavaScript
const defaults = { theme: "light", pageSize: 20 };
const options = { pageSize: 50 };

const settings = { ...defaults, ...options };

console.log(settings);
// 期待される結果: { theme: "light", pageSize: 50 }
console.log(defaults);
// 期待される結果: { theme: "light", pageSize: 20 }

状態更新や関数の引数処理など、元の値を直接変更せずに一部のプロパティだけを更新したい場面で使いやすい書き方です。

Object.assign()とスプレッド構文を比較する

比較項目Object.assign()スプレッド構文
基本構文Object.assign(target, source){ …source }
コピー先指定したtarget新しく作るオブジェクト
元オブジェクトへの影響targetに指定すると変更される通常は元オブジェクトを変更しない
代表的な用途既存のtargetへ値を適用するコピーや更新後の値を作る
Object.assign()とスプレッド構文の比較
JavaScript
const user = { name: "Aki", role: "user" };
const updates = { role: "admin" };

const byAssign = Object.assign({}, user, updates);
const bySpread = { ...user, ...updates };

console.log(byAssign);
// 期待される結果: { name: "Aki", role: "admin" }
console.log(bySpread);
// 期待される結果: { name: "Aki", role: "admin" }

通常のプレーンオブジェクトを単純に結合する場合は同じ結果になることがあります。ただし、特殊なオブジェクトやアクセサープロパティなどでは処理の仕組みが異なるため、常に機械的に置き換えられるとは限りません。

共通する注意点:コピーは基本的に浅いコピー

Object.assign()とオブジェクトのスプレッド構文は、トップレベルのプロパティをコピーします。しかし、ネストしたオブジェクトや配列は参照が共有されるため、内部の値まで独立して複製されるわけではありません。

JavaScript
const user = {
  name: "Aki",
  preferences: { theme: "light" }
};

const copiedUser = { ...user };
copiedUser.preferences.theme = "dark";

console.log(user.preferences.theme);
// 期待される結果: "dark"
// preferencesは元のuserとcopiedUserで同じ参照を共有しているため

複雑なデータを完全に独立させたい場合は、データ型や実行環境に応じて深いコピーの方法を検討してください。単純な設定値の結合と、データ全体の複製は分けて考えることが大切です。

開発現場での使い分け

  • 元のオブジェクトを変更せず、新しい値を作ることを明示したい場合はスプレッド構文を使う。
  • 既存のtargetへ複数の値をまとめて適用する処理ではObject.assign()を使う。
  • どちらを選ぶ場合も、後に指定・記述したプロパティが上書きする順序を確認する。
  • チームのコーディング規約や既存コードに合わせ、同じ目的の処理では記法を統一する。

参考