🙆
代入にも罠があった
関数の引数だとか、変数への代入だとかは頻繁にやるけど、実は2種類に分けることができる。
それは、値を入れるか、参照を入れるかの二つだ。まあ例を見ればわかる
const a = 10;
const b = a;
const b = 20;
console.log(a,b)
//10,20
const a = {text:"hello"}
const b = a;
b.text = "how are you?"
console.log(a,b)
//how are you? how are you?
これらの条件だが、オブジェクトかプリミティブかによって分岐する。
値がオブジェクトな変数を、ほかの変数に代入すると、それは参照渡しの状態になる。
値がプリミティブ型なら、それは値渡しになる。
ちなみに、オブジェクト変数を代入し、参照渡しになっても、ほかのオブジェクトを代入すれば、それは解除される。
let a = {a:1,};
let b = a;
b = {a:2};
console.log(a.a,b.a);
//1,2
オブジェクトを値渡しでコピーするには、浅いコピーと深いコピーの2通りのやり方がある。
浅いコピー
const a = {
shallow:1,
nest:{c:2}
}
const b = {...a}
b.shallow=10
b.nest.c=3;
console.log(a.shallow,b.shallow);
//1,10 独立してる
console.log(a.nest.c,b.nest.c);
//3,3 参照が渡されてて共有
深いコピー(めんどいので、多用するならライブラリとか使おう)
const a = {
shallow:1,
nest:{c:2}
}
const b = JSON.parse(JSON.stringify(a));
b.shallow=10
b.nest.c=3;
console.log(a.shallow,b.shallow);
//1,10 独立してる
console.log(a.nest.c,b.nest.c);
//2,3 ネストされた部分も独立
ただし、深いコピーは容量を食うので、必要な場合のみに使用
Discussion
インスタンスが共有されているだけなので、それは参照渡しではないのではないでしょうか?
※参照渡しが共有するのは変数であって オブジェクトではないです。
もしも参照渡しの様な変数の参照を渡す挙動を確認したい場合は import した変数を export 元で 代入するとその動作を確認することができます。
structuredClone おすすめします。