【JavaScript】オブジェクトや配列のコピーを作成する

【JavaScript】オブジェクトや配列のコピーを作成する

JavaScriptでオブジェクトや配列を別の変数に渡した場合、値ではなく参照のコピーが行われます。

そのため、コピー先に変更があった場合にはコピー元の値も変わってしまいます。

(function(){

    var srcObj;
    var copyObj;
    
    // コピー元を作成する
    srcObj = {};
    srcObj.val = 'A';
    
    // コピー先のオブジェクトを作成する
    copyObj = srcObj;
    copyObj.val = 'B';
    
    // コピー元
    console.log('src.val : ' + srcObj.val);     // B
    // コピー先
    console.log('copy.val : ' + copyObj.val);   // B
})();

上の例はオブジェクトですが、配列でも同じことが起こります。

調べてみると、配列の場合はsliceを使って簡単にコピーが出来る、というのが見つかります。

(function(){

    var srcArray;
    var copyArray;
    
    // コピー元を作成する
    srcArray = new Array();
    srcArray.push('A');
    
    // コピー先のオブジェクトを作成する
    copyArray = srcArray.slice(0, srcArray.length);
    copyArray[0] = 'B';
    
    // コピー元
    console.log('srcArray[0] : ' + srcArray[0]);    // A
    // コピー先
    console.log('copyArray[0] : ' + copyArray[0]);  // B
})();

しかし、配列内にオブジェクトが存在すると、この方法でも参照渡しになります。

(function(){

    var obj;
    var srcArray;
    var copyArray;
    
    // オブジェクトを作成する
    obj = {};
    obj.val = 'A';
    
    // コピー元を作成する
    srcArray = new Array();
    srcArray.push(obj);
    
    // コピー先のオブジェクトを作成する
    copyArray = srcArray.slice(0, srcArray.length);
    copyArray[0].val = 'B';
    
    // コピー元
    console.log('srcArray[0].val : ' + srcArray[0].val);    // B
    // コピー先
    console.log('copyArray[0].val : ' + copyArray[0].val);  // B
})();

これらはオブジェクトや配列としてコピーするから参照が渡されるわけです。

つまり、オブジェクトや配列としてコピーしなければ良いわけですね。

一度文字列に変換し、その文字列から復元すればどうでしょうか。

(function(){

    var obj;
    var srcArray;
    var copyArray;
    var jsonArray;
    
    // オブジェクトを作成する
    obj = {};
    obj.val = 'A';
    obj.func = function(){console.log('funcA');};
    
    // コピー元を作成する
    srcArray = new Array();
    srcArray.push(obj);
    
    // JSON文字列に変換する
    jsonArray = JSON.stringify(srcArray);
    
    // JSON文字列から配列を復元する
    copyArray = JSON.parse(jsonArray);
    copyArray[0].val = 'B';
    copyArray[0].func = function(){console.log('funcB');};
    
    // コピー元
    console.log('srcArray[0].val : ' + srcArray[0].val);    // A
    // コピー先
    console.log('copyArray[0].val : ' + copyArray[0].val);  // B
    
    srcArray[0].func();     // funcA
    copyArray[0].func();    // funcB
})();

値がコピーされているかと思います。

変数にfunctionなんかもコピーされるようです。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

No comments.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です