技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

JavaScript:オブジェクトの中身をコピーする方法(deepcopyライブラリ使用)

JavaScriptにもJavaC#と同じように参照型変数が存在し、オブジェクトや配列、関数が参照型変数です。
そして、JavaC#と同じように、単純に「=」で代入するだけでは参照先(オブジェクトのメモリ領域を示すポインタ)しかコピーできず、コピー先の変更がコピー元に影響してしまいますし、その逆にコピー元の変更がコピー先に影響してしまいます。
(このようなコピーを「シャローコピー(浅いコピー)」と呼びます)

これを避けたい場合には、参照しているメモリの中身を丸ごとコピー(新たにメモリ領域を確保し書き込み)する必要があります。
(このようなコピーを「ディープコピー(深いコピー)」と呼びます)
JavaScriptでは標準でディープコピーを行うための関数が用意されていないので、自力で実装するか、外部のライブラリを使用するかする必要があります。
今回は、deepcopy(https://www.npmjs.com/package/deepcopy)というライブラリを使用します。
(なお、ディープコピーをサポートするライブラリは他にもあり、用途に応じて使い分けた方が良いです。JSONシリアライズ・デシリアライズする方法もありますが、関数やundefinedがコピーされない等の問題があるので注意が必要です。)
 
以下、サンプルコードです。
Node.jsを使用して検証します。
 
【事前準備】
・Node.js command prompt を起動
・作業フォルダ(今回は"C:\tmp\")に移動
cd c:\tmp\
・deepcopyライブラリをインストール
npm install deepcopy
 
【サンプルコード】
サンプルコードは作業フォルダ直下に作成します。
 
・ShallowCopy.js
let item1 = {id:1, name:"Sword"};
let item2 = item1;
item2.id = 2; // オブジェクトのコピー
item2.name = "Shield";
console.log(item1);
console.log(item2);
 
・DeepCopy.js
const deepcopy = require('deepcopy'); // コピー用ライブラリ読込
let item1 = {id:1, name:"Sword"};
let item2 = deepcopy(item1); // オブジェクトのコピー
item2.id = 2;
item2.name = "Shield";
console.log(item1);
console.log(item2);
 
【実行結果】
c:\tmp>node ShallowCopy.js
{ id: 2, name: 'Shield' }
{ id: 2, name: 'Shield' }

c:\tmp>node DeepCopy.js
{ id: 1, name: 'Sword' }
{ id: 2, name: 'Shield' }

c:\tmp>