らばーいもっきんぐ

プログラミング等々についての覚え書き

【JavaScript】Object.assignでオブジェクトのコピーを作る

はじめに

参照型のデータを扱う際に、Object.assignメソッドを使ってオブジェクトのコピーを作る方法を学んだのでその記録です。

Object.assignとは

MDNの定義は以下。

Object.assign() メソッドは、すべての列挙可能なプロパティの値を、1つ以上のコピー元オブジェクトからコピー先オブジェクトにコピーするために使用されます。戻り値としてコピー先オブジェクトを返します。

使用例はこちら。

let a = { x: 1, y: 2, z: 3 };
let b = { x: 5, y: 6, };
let c = { x: 7 };

//戻り値としてコピー先のオブジェクト(a)を返す
Object.assign(a, b, c); //=> { x: 7, y: 6, z: 3 }

//コピー先のオブジェクト(a)は変更される
//コピー元のオブジェクト(bとc)は変更されない
console.log(a); //=> { x: 7, y: 6, z: 3 };
console.log(b); //=> { x: 5, y: 6, };
console.log(c); //=> { x: 7 };

Object.assignは第一引数の値(a)がコピー先になり、その後に続く値(b,c)がコピー元になる。

コピー先の値とコピー元の値がマージされる。

マージする際に、コピー先とコピー元に同じプロパティが存在する場合は、コピー元の値が優先され、コピー先の値は上書きされる。

コピー元の値が複数ある場合(上記例のbとc)は後のものが優先される(bよりcが優先される)

上記の例では、変数aのyの値は変数bのyで上書きされ6になる。変数aのxの値は変数bのxの値で上書きされ、さらに変数cのxの値で上書きされるため、結果的に7になる。

Object.assingでコピーを作る

例えば以下のような場合。

let a = { x: 1, y: 2, z: 3 };
let b = a;

console.log(b); //=> { x: 1, y: 2, z: 3 };

a["x"] = 10;

console.log(a); //=> { x: 10, y: 2, z: 3 };
console.log(b); //=> { x: 10, y: 2, z: 3 };

JavaScriptでは配列やオブジェクトは参照型のため、aの値が変更されるとbの値も変更されてしまう。

そこで、aのコピーを作り、それを利用すればbに影響を与えずに済む。 コピーを作るには以下のようにする。

let a = { x: 1, y: 2, z: 3 };
let b = a;
// aのコピーを作り、変数cに代入する
let c = Object.assign( {}, a );

// 変数cにはaの値がコピーされている
console.log(c) //=> { x: 1, y: 2, z: 3 };

// 変数cの値を変更する
c["x"] = 10;

console.log(a) //=> { x: 1, y: 2, z: 3 };
console.log(b) //=> { x: 1, y: 2, z: 3 };
console.log(c) //=> { x: 10, y: 2, z: 3 };

Object.assignの第一引数(コピー先)に空のオブジェクトを用意し、コピー元の要素を第二引数以降に指定する。

aとcは別のオブジェクトになるため、cの値をいくら変更してもコピー元のaには影響せず、また、aを参照するbにも当然ながら影響を与えない。

まとめ

参照型の挙動を意識していないと、思わぬところに影響を与える可能性があるので注意しましょう。