記事下部にコメント指摘の追記あります。
やりたいこと
人類において200000000回は繰り返されているであろう事象。
それはObjectをコピーして、コピーした方の中身を入れ替えたはずが、
コピー元まで入れ替わってしまっているということ。
これはObjectも(もちろんArrayも)参照先をコピーしてしまうことに起因する。
四次元ポケットと似た仕組みだ。(入り口は異なれど中身は一緒)
// あるObjectがあって、
const ObjectA = {
a:'dog',
b:'cat',
c:'bird',
};
// それをコピーする必要があった
const ObjectB = ObjectA;
// コピーした方の中身をちょっとだけ変えたい
ObjectB.a = 'dragon';
// あれ!?!?コピー元まで変わってる!?!?
console.log(ObjectA.a);
//欲しい結果= dog
//実際の結果= dragon
解決策
そこで、Object.assign()を応用します。
const ObjectB = Object.assign({}, ObjectA);
const ObjectA = {
a:'dog',
b:'cat',
c:'bird',
};
//メソッド第一引数のassignが必須。これで新規のObjectに入れ直している。
const ObjectB = Object.assign({}, ObjectA);
// コピーした方の中身を変える
ObjectB.a = 'dragon';
// コピー元は変わってない!コピーした先だけが変わってる!ヨシっ!
console.log(ObjectA.a);
console.log(ObjectB.a);
//実際の結果
// ObjectA.a = 'dog'
// ObjectB.a = 'dragon'
ただこれもシャローコピー(1階層目のみのコピー)なので、
ネストになっていた場合は以下のように参照先がコピーされてしまいます。
// Objectの中にObjectを作る
const ObjectA = { animal: { a: 'dog', b: 'cat' }, creature: { a: 'dragon', d: 'harpy' } };
// さっきと同じく、Object.assign()でコピーする
const ObjectB = Object.assign({}, ObjectA);
// よっしゃ、animalのaを'bird'に入れ替えたろ!
ObjectB.animal.a = 'bird';
console.log(ObjectA.animal.a);
console.log(ObjectB.animal.a);
// 実際の結果= 両方とも'bird'
ディープコピーはやり方を調べると色々でてきますが、
自前でメソッドを定義するのはわりと大変です。
配列であればmap関数などで中身を入れ替えちゃえば良いのですが、
オブジェクトの場合はそうもいきません。
ただディープコピーは多くの人たちが必要としていることもあり、
いろんな言語に対応するライブラリが作られています。
そういうのを使ってみるのも、良いかもしれませんね!(投げやり)
参考:
Jqueryであればextendとか。
https://api.jquery.com/jquery.extend/
もっとわかりやすくかける方法(コメント指摘)
スプレッド構文で書くのが今風ということで、しかもこっちの方が見やすくてわかりやすいですね(IE対応、assignもできないし)
// {}の空オブジェクトに、ObjectAの中身をスプレッド構文で展開してあげる
const ObjectB = { ...ObjectA };
// コピーした方の中身を変える
ObjectB.a = 'dragon';
// コピー元は変わってない!コピーした先だけが変わってる!ヨシっ!
console.log(ObjectA.a);
console.log(ObjectB.a);
//実際の結果
// ObjectA.a = 'dog'
// ObjectB.a = 'dragon'