2015-03-05 4 views
11

Ich versuche, Array von verschachtelten Objekten in Javascript zu tief zu kopieren. Meine Array aussehen wie diesesTief kopieren Array verschachtelter Objekte in Javascript

var arr = [{name:"adam",age:"21"}, 
    {name:"freddie",age:"35",children:[{name:"mercury",age:"25"}]}, 
    {name:"jim",age:"35",children:[{name:"morrison",age:"25",children:[{name:"some", age:"40"}]}]} 
    ]; 

ich eine tiefe Kopie jedes Objekt innerhalb des Arrays machen wollen, dass ich eine exakte Kopie von arr in neue Array erstellen möchten, die nicht Gegenstand Bezug haben sollte. Die Tiefe des Arrays ist ebenfalls unbekannt, dh das Child-Array kann bis zu einem beliebigen Level reichen. Ich bin durch diesen Link Copying of an array of objects to another Array without object reference in javascript(Deep copy) gegangen, aber das hat mir nicht geholfen. Ich habe gegoogelt und einige Lösungen in jQuery gefunden, aber das hat mir nicht geholfen, da ich kein Wissen über jQuery habe.

Ich habe auch versucht es mit Rekursion Implementierung aber das ist nicht zu arbeiten http://ideone.com/kJi5X3

ich es in Javascript, ohne mit jQuery oder etwas nur tun wollen. Ich bin neu in JavaScript, also habe ich vielleicht verpasst, wenn es eine Bibliothek oder eine einfache Methode dafür gibt. Bitte helfen Sie mir, dieses Problem zu lösen. Danke im Voraus.

+1

Sie haben mit einer Frage verknüpft, dass dies als ein Duplikat geschlossen sein könnte und sagte, es habe nicht geholfen - können Sie erklären, warum es nicht geholfen hat, also verstehen wir, warum das kein Duplikat von diesem ist? –

+0

Beachten Sie auch, dass jQuery _just eine javascript library_ ist, wenn es eine jQuery-Lösung gäbe, schließen Sie diese Bibliothek aus, während eine andere akzeptabel wäre? –

+0

@James Thorpe - Nein, ich frage mich, ob es eine Möglichkeit gibt, es mit Rekursion oder einer anderen Logik zu tun, ich habe keine Kenntnisse von jQuery und ich möchte dies so schnell wie möglich tun. – user2912611

Antwort

24

Sie haben zwei Möglichkeiten:

  1. Verwenden JSON.stringify und JSON.parse:

    var copy = JSON.parse(JSON.stringify(original)); 
    

    Aber Ich habe das nie gemocht. Ein Umlauf durch Text ist bestenfalls ineffizient und wird Date, RegExp, undefined usw. nicht korrekt verarbeiten, es sei denn, Sie schreiben einen Ersetzer und einen Reviver.

  2. Verwenden Sie eine rekursive Funktion, so etwas wie dieses:

var toString = Object.prototype.toString; 
 
function deepCopy(obj) { 
 
    var rv; 
 

 
    switch (typeof obj) { 
 
     case "object": 
 
      if (obj === null) { 
 
       // null => null 
 
       rv = null; 
 
      } else { 
 
       switch (toString.call(obj)) { 
 
        case "[object Array]": 
 
         // It's an array, create a new array with 
 
         // deep copies of the entries 
 
         rv = obj.map(deepCopy); 
 
         break; 
 
        case "[object Date]": 
 
         // Clone the date 
 
         rv = new Date(obj); 
 
         break; 
 
        case "[object RegExp]": 
 
         // Clone the RegExp 
 
         rv = new RegExp(obj); 
 
         break; 
 
        // ...probably a few others 
 
        default: 
 
         // Some other kind of object, deep-copy its 
 
         // properties into a new object 
 
         rv = Object.keys(obj).reduce(function(prev, key) { 
 
          prev[key] = deepCopy(obj[key]); 
 
          return prev; 
 
         }, {}); 
 
         break; 
 
       } 
 
      } 
 
      break; 
 
     default: 
 
      // It's a primitive, copy via assignment 
 
      rv = obj; 
 
      break; 
 
    } 
 
    return rv; 
 
} 
 
var a = [1, {foo: "bar"}, ['a', 'b'], new Date()]; 
 
snippet.log(JSON.stringify(a)); 
 
var b = deepCopy(a); 
 
snippet.log(JSON.stringify(b));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Beachten Sie, dass die oben verwendet ES5 auf allen modernen Browsern verfügt aber nicht einigen älteren, wie IE8 . Alle oben genannten Funktionen können für ältere Browser jedoch mehrfach ausgeführt werden.

Das versucht nicht, mit benutzerdefinierten Konstruktorfunktionen umzugehen oder Prototypen für Objekte im Array zu erhalten; Dadurch werden die Dinge dramatisch komplizierter und unmöglich, ohne eine Konvention zu machen, wie diese Konstruktoren für einen Kopiervorgang aufgerufen werden. Sie können sich nähern, indem Sie den gleichen Prototyp zuweisen, aber das würde Logik in der Konstruktorfunktion nicht berücksichtigen und insbesondere für Funktionen, die als Schließungen darin eingerichtet sind.

+0

Crowder, die einwandfrei funktionierte, vielen Dank :) – user2912611