Object.assignの挙動で勘違いしていたこと
知ってる人からしたら、なにをいまさらという感じかもしれませんが Object.assignの挙動に関して勘違いしていたことがあり、業務中にハマったので備忘録程度に書きます。
勘違い1:Object.assignの返り値
Object.assignの返り値について勘違いしていました。 引数で渡したオブジェクトを合成した新しいオブジェクトを返す
のではなく
第2引数以降に渡したオブジェクトを、第1引数に渡したオブジェクトに合成して返す
ものでした。 MDNにも
Object.assign() メソッドは、すべての列挙可能なプロパティの値を、1つ以上のコピー元オブジェクトからコピー先オブジェクトにコピーするために使用されます。戻り値としてコピー先オブジェクトを返します。
Object.assign() - JavaScript | MDN
と書いてありました。
よって、以下のように
const obj1 = { a: 1, b: 2 }; const obj2 = { b: 4, c: 5 }; const obj3 = Object.assign(obj1, obj2); console.log(obj1); // { a: 1, b: 4, c: 5 } console.log(obj3); // { a: 1, b: 4, c: 5 }
obj1もobj3も中身が書き換わった状態になっています。
勘違い2:引数で渡したオブジェクトがネストされているときの挙動
Object.assignはシャローコピーのため、第2引数以降に渡したオブジェクトがネストされていた場合、オブジェクト参照がコピーされるようです。
const obj1 = {a:1, b:2}; const obj2 = {b:3, c:4, d:{a:5, b:6}}; Object.assign(obj1, obj2); console.log(obj1); // {a:1, b:3, c:4, d:{a:5, b:6}} obj1.d.a = 999; // obj1.d.aの値を更新する console.log(obj1); // {a:1, b:3, c:4, d:{a:999, b:6}} console.log(obj2); // {b:3, c:4, d:{a:999, b:6}} →オブジェクト参照がコピーされているため、obj2.d.aの値が変わっている
コピー先の変更についてコピー元に影響を及ぼしたくないときは ディープコピーしたオブジェクトをコピー元として渡すなりすればよさそうです。
おわりに
初歩的な内容にはなりましたが、このような勘違いしていたこと、業務中ハマった内容は 小さなことでも書いていきたいと思います。