JavaScriptでのオブジェクトコピーについてのメモ
※2020/10/31 追記
@standard-softwareさんのコメントより、Object.assignを非破壊的に使う方法を教えていただいたので追記しました。
概要
JavaScriptでオブジェクトをコピーしたいときに2つの書き方がある
- Object.assign(コピー先, コピー元)を使う
- スプレッド構文を使う
Object.assign(コピー先, コピー元)を使う
Object.assign() メソッドは、すべての列挙可能な自身のプロパティの値を、1つ以上のコピー元オブジェクトからコピー先オブジェクトにコピーするために使用されます。
Object.assign() - JavaScript | MDN
※ Object.assignはコピー先のオブジェクトそのものを書き換える破壊的メソッド
const targetObj = {
key1: 'value1',
key2: 'value2'
};
const copyObj = Object.assign(targetObj, {key3: 'value3'});
console.log(copyObj);
// { key1: 'value1', key2: 'value2', key3: 'value3' }
// Object.assignはtargetObj自体を書き換える破壊的メソッドであることを確認
const targetObj2 = {
key1: 'value1',
key2: 'value2'
};
console.log('before : ', targetObj2);
const copyObj2 = Object.assign(targetObj2, sourceObj);
console.log('after : ', targetObj2);
// before : { key1: 'value1', key2: 'value2' }
// after : { key1: 'value1', key2: 'value2', key3: 'value3' }
※ Object.assignを非破壊的に使うことも可能(2020/10/31追記)
// Object.assginを非破壊的に使うこともできる
const targetObj1 = {
key1: 'value1',
key2: 'value2'
};
const targetObj2 = {
key3: 'value3',
key4: 'value4'
};
console.log('before : ', targetObj1);
// before : { key1: 'value1', key2: 'value2' }
// 空オブジェクトに1と2をコピーすれば、targetObj1を汚染しない
const resultObj = Object.assign({}, targetObj1, targetObj2);
console.log('after : ', targetObj1);
// after : { key1: 'value1', key2: 'value2' }
console.log('result : ', resultObj);
// result : { key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4' }
スプレッド構文を使う
※ Object.assignと異なり、非破壊的メソッド
コピー先を変えずに、プロパティを追加した新しいオブジェクトを作成できるため、こちらを使う方がよい
const targetObj = {
key1: 'value1',
key2: 'value2'
};
const sourceObj = { key3: 'value3'};
const copyObj = {...targetObj, ...sourceObj};
console.log('copyObj : ', copyObj);
// copyObj : { key1: 'value1', key2: 'value2', key3: 'value3' }
console.log('targetObj : ', targetObj);
// targetObj : { key1: 'value1', key2: 'value2' }
注意事項
どちらもシャローコピーになるため、プロパティの値がオブジェクトだった場合、参照のみがコピーされる。
下記では、
・ bookCopy.nameを変更してもbook.nameに影響はない
・ bookCopy.relatedBook.nameを変更すると、book.relatedBook.nameも変更されてしまっている。
const book = {
name: '独学大全',
author: '読書猿',
relatedBooks: {
name: '問題解決大全'
}
}
const price = { price: 1000 }
const bookCopy = {...book, ...price}
console.log(bookCopy);
/*
{
name: '独学大全',
author: '読書猿',
relatedBooks: { name: '問題解決大全' },
price: 1000
}
*/
// bookCopyオブジェクトのnameを変更する
bookCopy.name = 'アイデア大全';
// bookCopyオブジェクトのrelatedBooks.nameを変更する
bookCopy.relatedBooks.name = '新刊?'
console.log('bookCopy : ', bookCopy.relatedBooks.name);
console.log('book : ', book.relatedBooks.name);
// bookCopy : 新刊?
// book : 新刊?