web-dev-qa-db-ja.com

JSONを使用したjavascriptディープコピー

Javascript object(array)deep copyに問題があります。私はそれに対処するための多くの良い方法を読みました。また、jQueryにはこの問題に対する$ .extend APIがあることも知っています。しかし、私の質問は次のとおりです。この問題を解決するためにJSONのstringifyおよびparseメソッドを使用できますか?

ここに私のコードがあります:

function deepCopy(oldValue) { 
  var newValue
  strValue = JSON.stringify(oldValue)
  return newValue = JSON.parse(strValue)
}

var a = {
  b: 'b',
  c: [1,2,4],
  d: null
}

copy = deepCopy(a)

console.log(a === copy) // false
console.log(a.c === copy.c) // false

PS:すべてのオブジェクトがシリアル化できない場合、私が知っている唯一の状況は、オブジェクトに関数であるプロパティが含まれている場合です。他の状況は?

20
user2666750

オブジェクトが「小さく」、シリアル化可能なプロパティのみを含む場合、JSONシリアル化を使用した単純なdeepCopyハックは問題ありません。しかし、オブジェクトが大きい場合、問題が発生する可能性があります。そして、シリアライズできないプロパティが含まれている場合、それらは失われます:

_var o = {
 a: 1,
 b: 2,
 sum: function() { return a + b; }
};

var o2 = JSON.parse(JSON.stringify(o));
console.log(o2);
_

利回り:

_Object {a: 1, b: 2}
_

興味深いことに、C#のかなりの数のディープコピーソリューションは、同様のシリアル化/逆シリアル化のトリックです。

補遺:コピー後のオブジェクトの比較に関して、あなたが何を望んでいるかわからない。ただし、複雑なオブジェクトの場合、通常、正確な比較のために独自のCompare()および/またはEquals()メソッドを記述する必要があります。

また、注目すべきは、この種のコピーでは型情報が保持されないことです。

_JSON.parse(JSON.stringify(new A())) instanceof A === false
_
36
svidgen

そのようにすることはできますが、上記のいくつかの理由で問題があります。

  1. パフォーマンスに疑問があります。

  2. シリアル化できないプロパティはありますか?

  3. そして最大:クローンには型情報がありません。何をしているのかにもよりますが、それは重要です。実装者は、元のオブジェクトのプロトタイプにメソッドを追加しましたか?それらはなくなりました。他に何を失うかはわかりません。

3
Joseph Larson