web-dev-qa-db-ja.com

オブジェクトの配列をjavascriptの別の配列にコピーする(ディープコピー)

Slice(0)およびconcat()を使用してオブジェクトの配列をJavaScriptの別の配列にコピーすることはできません。

私はこれを使用してディープコピーの予想される動作を得るかどうかをテストするために次を試しました。しかし、コピーした配列に変更を加えた後、元の配列も変更されています。

var tags = [];
for(var i=0; i<3; i++) {
    tags.Push({
        sortOrder: i,
        type: 'miss'
    })
}
for(var tag in tags) { 
    if(tags[tag].sortOrder == 1) {
        tags[tag].type = 'done'
    }
}
console.dir(tags)

var copy = tags.slice(0)
console.dir(copy)

copy[0].type = 'test'
console.dir(tags)

var another = tags.concat()
another[0].type = 'miss'
console.dir(tags)

配列のコピーを変更しても元の配列が変更されないように、配列を別の配列にディープコピーするにはどうすればよいですか。

19
jsbisht

試して

var copy = JSON.parse(JSON.stringify(tags));
68
dangh

以下をお試しください

// Deep copy
var newArray = jQuery.extend(true, [], oldArray);

詳細については、この質問を確認してください JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?

14
Marko

前述のようにここ.slice(0)は、プリミティブ型の要素を持つ配列を複製するのに有効です。ただし、この例では、tags配列に匿名オブジェクトが含まれています。したがって、クローン配列内のこれらのオブジェクトに対する変更は、tags配列に反映されます。

上記の@danghの返信では、これらの要素オブジェクトの参照が解除され、新しいオブジェクトが作成されます。

別のスレッドがあります同様の状況に対処する

4
Bhanuprakash D

ES6でオブジェクトの配列を複製する良い方法は、スプレッド構文を使用することです:

const clonedArray = [...oldArray];

[〜#〜] mdn [〜#〜]

2
Binaromong

これを1行で行う最も簡単で楽観的な方法は、アンダースコア/ロダッシュを使用することです

let a = _.map(b、_.clone)

0
user8876438

私はこれが少し古い記事であることを知っていますが、幸運にも配列をディープコピーする適切な方法を見つけました。配列、オブジェクトを含むもの、そして配列を含むオブジェクトさえもコピーされます...私は1つの問題しか見ることができませんこのコードでは、十分なメモリがない場合、配列とオブジェクトの非常に大きな配列でこの窒息を見ることができます...しかし、大部分は動作するはずです。ここに投稿している理由は、参照ではなく値でオブジェクトの配列をコピーするOPリクエストを達成するためです...ので、コードで(チェックはSO、私が自分で書いたメインコピー関数からのものであり、他の誰かがおそらく以前に書いたことがないこと、私はそれらに気付いていないだけです)::

var isArray = function(a){return (!!a) && (a.constructor===Array);}
var isObject = function(a){return (!!a) && (a.constructor===Object);}
Array.prototype.copy = function(){
    var newvals=[],
        self=this;
    for(var i = 0;i < self.length;i++){
        var e=self[i];
        if(isObject(e)){
            var tmp={},
                oKeys=Object.keys(e);
            for(var x = 0;x < oKeys.length;x++){
                var oks=oKeys[x];
                if(isArray(e[oks])){
                    tmp[oks]=e[oks].copy();
                } else { 
                    tmp[oks]=e[oks];
                }
            }
            newvals.Push(tmp);
        } else {
            if(isArray(e)){
                newvals.Push(e.copy());
            } else {
                newvals.Push(e);
            }
        }
    }
    return newvals;
}

この関数(Array.prototype.copy)は、必要に応じて値を返すオブジェクトまたは配列が呼び出されると、再帰を使用して自己を呼び出します。このプロセスはまともなスピードで、あなたがやりたいことを正確に行い、値によって配列の深いコピーを行います...クロムとIE11でテストされ、これらの2つのブラウザーで動作します。

0
Jesse Fender

'...'表記を使用するだけです。

// THE FOLLOWING LINE COPIES all elements of 'tags' INTO 'copy'
var copy = [...tags]

Xという配列がある場合、[... x]はxのすべての値で新しい配列を作成します。この表記はオブジェクト上でわずかに異なる動作をするので注意してください。オブジェクトをすべてのキーと値のペアに分割します。したがって、オブジェクトのすべてのキーと値のペアを関数に渡したい場合は、function({... obj})を渡すだけです。

0
Anant Sinha

私にも同じ問題が起こります。サービスからのデータがあり、別の変数に保存します。アレイを更新すると、コピーされたアレイも更新されます。古いコードは以下のようなものです

_//$scope.MyData get from service
$scope.MyDataOriginal = $scope.MyData;_

したがって、$ scope.MyDataを変更すると、$ scope.MyDataOriginalも変更されます。以下のようにangular.copyの正しいコードのソリューションを見つけました

$scope.MyDataOriginal = angular.copy($scope.MyData);
0
Biby Cheriyan