JavaScriptにおけるオブジェクトスプレッドとObject.assignの違い
オブジェクトスプレッドとObject.assignは、JavaScriptのオブジェクトを操作するための2つの強力な手法です。どちらも既存のオブジェクトから新しいオブジェクトを作成する際に役立ちますが、その挙動や用途は若干異なります。
オブジェクトスプレッド
オブジェクトスプレッドは、ES6で導入されたシンタックスです。既存のオブジェクトのプロパティを新しいオブジェクトに展開(スプレッド)する際に使用されます。
const originalObject = { name: "Alice", age: 30 };
const newObject = { ...originalObject, city: "Tokyo" };
console.log(newObject); // Output: { name: 'Alice', age: 30, city: 'Tokyo' }
この例では、originalObject
のプロパティが新しいオブジェクトnewObject
に展開され、さらに新しいプロパティcity
が追加されています。
Object.assign
Object.assign
は、ES6で導入された組み込み関数です。既存のオブジェクトのプロパティを別のオブジェクトにコピーする際に使用されます。
const originalObject = { name: "Alice", age: 30 };
const newObject = Object.assign({}, originalObject, { city: "Tokyo" });
console.log(newObject); // Output: { name: 'Alice', age: 30, city: 'Tokyo' }
この例では、Object.assign
を使用して、originalObject
のプロパティを空のオブジェクトにコピーし、さらに新しいプロパティcity
を追加しています。
重要な違い
- オブジェクトの変更: オブジェクトスプレッドは新しいオブジェクトを作成するため、元のオブジェクトを変更しません。一方、
Object.assign
は既存のオブジェクトを変更することがあります。 - プロパティの重複: オブジェクトスプレッドは、同じ名前のプロパティが重複した場合、後続のプロパティが優先されます。
Object.assign
は、重複するプロパティを上書きします。 - ネストされたオブジェクト: オブジェクトスプレッドはネストされたオブジェクトを浅くコピーします。
Object.assign
も同様に浅いコピーを行います。
いつどちらを使うべきか
- 新しいオブジェクトを作成したい場合: オブジェクトスプレッドが一般的に推奨されます。
- 既存のオブジェクトを変更したい場合:
Object.assign
を使用できますが、注意が必要です。 - ネストされたオブジェクトの深いコピーが必要な場合:
JSON.parse(JSON.stringify(object))
を使用することもできますが、パフォーマンスに影響を与える可能性があります。
オブジェクトスプレッドとObject.assignの具体的な例と解説
// 元のオブジェクト
const person = {
name: '太郎',
age: 30
};
// 新しいオブジェクトを作成(スプレッド構文)
const newPerson = {
...person,
city: '東京'
};
console.log(newPerson); // 出力: { name: '太郎', age: 30, city: '東京' }
解説:
...person
の部分で、person
オブジェクトのプロパティが全てnewPerson
に展開されます。- 既存の
person
オブジェクトは変更されません。 - 新しいプロパティ
city
を追加することができます。
const person = {
name: '太郎',
age: 30
};
const newPerson = Object.assign({}, person, { city: '東京' });
console.log(newPerson); // 出力: { name: '太郎', age: 30, city: '東京' }
Object.assign
の第一引数に空のオブジェクト{}
を指定することで、新しいオブジェクトを作成します。- 第二引数以降にコピー元のオブジェクトを指定します。
- 複数のオブジェクトを指定した場合、後続のオブジェクトのプロパティが前のオブジェクトのプロパティを上書きします。
オブジェクト操作の2つの方法の比較
特徴 | オブジェクトスプレッド | Object.assign |
---|---|---|
構文 | 简潔で直感的 | メソッド呼び出し |
新しいオブジェクトの作成 | 容易 | 第一引数に空のオブジェクトを指定 |
既存オブジェクトの変更 | しない | 変更する可能性がある |
プロパティの重複 | 後続のプロパティが優先 | 後続のプロパティで上書き |
ネストされたオブジェクト | 浅いコピー | 浅いコピー |
- 複数のオブジェクトをマージしたい場合: Object.assignが便利です。
オブジェクトスプレッドとObject.assignは、どちらもオブジェクトを操作するための強力なツールです。それぞれの特性を理解し、適切な場面で使い分けることで、より効率的なJavaScriptプログラミングが可能になります。
- ES2015以降の機能: オブジェクトスプレッドとObject.assignは、ES2015(ES6)で導入された機能です。
より深い理解のために:
- MDN Web Docs:
- Qiitaの記事:
Object.keys()とfor...inループ
**Object.keys()**でオブジェクトのキーを取得し、for...inループを使って新しいオブジェクトにコピーしていく方法です。
const originalObject = { name: '太郎', age: 30 };
const newObject = {};
for (const key in originalObject) {
if (originalObject.hasOwnProperty(key)) {
newObject[key] = originalObject[key];
}
}
// 新しいプロパティを追加
newObject.city = '東京';
- **Object.keys()**で
originalObject
の全てのキーを取得します。 - for...inループで各キーに対して、新しいオブジェクト
newObject
にコピーします。 hasOwnProperty()
を使って、プロトタイプチェーンから継承されたプロパティを避けることができます。
メリット:
- 柔軟な操作が可能
- 古くからあるJavaScriptの機能なので、全ての環境で動作する
- 手間がかかる
- 可読性がやや落ちる
JSON.parse()とJSON.stringify()
オブジェクトをJSON文字列に変換し、再度パースすることで、深いコピーを作成する方法です。
const originalObject = { name: '太郎', age: 30 };
const newObject = JSON.parse(JSON.stringify(originalObject));
JSON.stringify()
でオブジェクトをJSON文字列に変換します。JSON.parse()
でJSON文字列をオブジェクトに戻します。
- 深いコピーが簡単に作成できる
- シンプルなコード
- パフォーマンスが若干低下する
- サークル参照や関数などの特殊なオブジェクトは正しくコピーできない場合がある
LodashやRamdaなどのライブラリ
LodashやRamdaなどのユーティリティライブラリには、オブジェクトの操作に関する様々な関数があります。
// Lodashの例
const _ = require('lodash');
const newObject = _.cloneDeep(originalObject);
- 高度な機能が豊富
- 可読性が高い
- ライブラリを導入する必要がある
どの方法を選ぶべきか
- シンプルなコピー: オブジェクトスプレッドやObject.assignが最も簡単
- 深いコピー: JSON.parse()とJSON.stringify()、またはLodashなどのライブラリ
- パフォーマンス: 状況によって異なるため、ベンチマークを取ることをおすすめします
オブジェクトスプレッドとObject.assignは、現代のJavaScriptでは最も一般的な方法ですが、状況に応じて他の方法も検討することができます。それぞれのメリットデメリットを理解し、最適な方法を選択しましょう。
- パフォーマンス: 実際のアプリケーションでは、パフォーマンスの違いはほとんど無視できる場合が多いですが、大規模なデータ処理などでは、パフォーマンスが重要な要素となることがあります。
javascript ecmascript-6