落とし穴
JavaScript のオブジェクトは参照型ですからオブジェクト、配列は参照渡しになります。よく理解していないと値を更新しても期待通り動作しません。最悪バグを生むことになりかねません。(大抵の場合こういった類のバグは潰すのが大変だったりします)
// myCar という名前のオブジェクトを作成 const myCar = { make: 'Ford', model: 'Mustang', year: 1969 }; // newCar は異なるオブジェクトのつもり // 実際は、同じオブジェクトへの参照になっている let newCar = myCar; // newCar のプロパティーを変更する newCar.make = 'Bayerische Motoren Werke AG'; newCar.model = 'BMW M8 グラン クーペ'; newCar.year = 2021; // newCar は変更できたが ... console.log('newCar=', newCar); // > "newCar=" Object { make: "Bayerische Motoren Werke AG", model: "BMW M8 グラン クーペ", year: 2021 } // 実は myCar まで書き換わっている console.log('myCar=', myCar); // > "myCar=" Object { make: "Bayerische Motoren Werke AG", model: "BMW M8 グラン クーペ", year: 2021 } // myCar を代入して、初期値に戻したいが。。。 newCar= myCar; console.log('newCar=', newCar); // > "newCar=" Object { make: "Bayerische Motoren Werke AG", model: "BMW M8 グラン クーペ", year: 2021 }
ぢゃ どうすればいい
オブジェクトや配列を代入するのではなく、ディープ コピーを使う。 コピーには、ディープとシャローがあるということを学習しておきたい。
![](https://stat.ameba.jp/user_images/20210204/08/hero-design/a6/28/g/o0400019014891176854.gif?caw=800)
対策![](https://stat.ameba.jp/user_images/20210206/11/hero-design/24/54/p/o0030003014892163579.png?caw=800)
JSON.stringify() で文字列に変換し JSON.parse() でオブジェクトに戻すことでコピーする。ただし、このやり方は Date 型のプロパティ値を正しく復元できなくなるという問題がある。
let newCar = JSON.parse(JSON.stringify(myCar));
対策![](https://stat.ameba.jp/user_images/20210206/12/hero-design/71/0f/p/o0030003014892163704.png?caw=800)
Object.assign() を使う。ただし、オブジェクト内にオブジェクトがある場合は、中のオブジェクトが参照渡しになってしまうので注意する。
let newCar = Object.assign({}, myCar);
対策![](https://stat.ameba.jp/user_images/20210206/12/hero-design/6a/ef/p/o0030003014892163856.png?caw=800)
Lodash の cloneDeep() を使う。
Installation
Using npm:$ npm i --save lodash.clonedeepIn Node.js:
const cloneDeep = require('lodash.clonedeep'); let newCar = cloneDeep(myCar);
対策![](https://stat.ameba.jp/user_images/20210206/12/hero-design/52/3d/p/o0030003014892163906.png?caw=800)
配列は、concat() を使う。
const old_array = [ 1, 2, 3 ]; const new_array = old_array.concat();