やりたいこと
Const State = {
name: ‘Hanako’,
stay: {
Japan: {
Hiroshima: ‘実家’,
Karuizawa: ‘別荘’,
},
America: {
NewYork: ‘別荘’,
Arizona: ‘おじいちゃんち’
}
}
};
これのKaruizawaを'実家2'にしたコピーが欲しい!
StateのstayのJapanのKaruizawaが書き換わるのはいやだ
Object.assign()は浅いコピーのため、一回のコピーでご丁寧に入れ子の中までコピーはしてくれません。
今の状態で、State2を定義して、Stateをコピーした後、Karuizawaの中身をみると、
Const State2 = Object.assign({}, State);
Console.log(State.stay.Japan.Karuizawa);
-> 別荘
試しに、State2.stay.Japan.Karuizawa に'実家2'を代入してみます。
失敗例1
State2.stay.Japan.Karuizawa = ‘実家2’;
Console.log(State.stay.Japan.Karuizawa);
-> 実家2
これだと、最初のStateの中のKaruizawaが'別荘'ではなく、'実家2'に書き変わってしまっています。
そうじゃない。Karuizawaが'別荘'のバージョンと'実家2'のバージョンの二つが欲しい、書き変わってほしくないので、このコピーは失敗です。
失敗例2
State2= Object.assign({}, State);
State2.stay.Japan= Object.assign({}, State.stay.Japan, { Karuizawa: ‘実家2’} )
Console.log(State.stay.Japan.Karuizawa);
-> 実家2
↑このパターンも書き変わってしまいます。失敗・・・
では、成功例はというと、
成功例
State2= Object.assign({}, State);
State2.stay = Object.assign({}, State.stay);
State2.stay.Japan = Object.assign({}, State.stay.Japan);
State2.stay.Japan = Object.assign({}, State.stay.Japan, { Karuizawa: '実家2'});
一旦ここまで丁寧にコピーしてやります。
それぞれの中身をみてみましょう。
console.log(State2);
=>{ name: 'Hanako',
stay:
{ Japan: { Hiroshima: '実家', Karuizawa: '実家2' },
America: { NewYork: '別荘', Arizona: 'おじいちゃんち' } } }
console.log(State2.stay.Japan.Karuizawa);
=>実家2
console.log(state.stay.Japan.Karuizawa);
=>別荘
Stateの方のKaruizawaは '別荘' のままです。書き変わってません!成功です!!
シャローコピーで粘りたい方は、この方法おすすめです。