... wo jedes Objekt auch Verweise auf andere Objekte innerhalb desselben Arrays hat?
Als ich zum ersten Mal auf dieses Problem kam, dachte ich nur an so etwas
var clonedNodesArray = nodesArray.clone()
würde existieren und nach Informationen suchen, wie man Objekte in Javascript klont. Ich habe eine Frage zu StackOverflow gefunden (beantwortet von @JohnResig) und er hat darauf hingewiesen, dass Sie dies mit jQuery tun können
var clonedNodesArray = jQuery.extend({}, nodesArray);
ein Objekt klonen. Ich habe dies versucht, dies kopiert nur die Referenzen der Objekte im Array. Also wenn ich
nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"
Der Wert von NodesArray [0] und ClonedNodesArray [0] wird als "grün" angezeigt. Dann habe ich es versucht
var clonedNodesArray = jQuery.extend(true, {}, nodesArray);
Das Deep kopiert ein Objekt, aber ich habe sowohl von Firebug als auch von Opera Dragonfly die Meldung " Zu viel Rekursion " und " Kontrollstapelüberlauf " erhalten.
Wie würdest du es machen? Ist das etwas, was nicht einmal getan werden sollte? Gibt es eine wiederverwendbare Möglichkeit, dies in Javascript zu tun?
quelle
Solange Ihre Objekte JSON-serialisierbaren Inhalt enthalten (keine Funktionen, keine
Number.POSITIVE_INFINITY
usw.), sind keine Schleifen zum Klonen von Arrays oder Objekten erforderlich. Hier ist eine reine Vanille-Einzeilenlösung.Um die folgenden Kommentare zusammenzufassen, besteht der Hauptvorteil dieses Ansatzes darin, dass auch der Inhalt des Arrays geklont wird, nicht nur das Array selbst. Die Hauptnachteile sind die Beschränkung, nur an JSON-serialisierbaren Inhalten zu arbeiten, und die Leistung (die erheblich schlechter ist als bei a
slice
basierter Ansatz).quelle
null
undundefined
werden Probleme sein, da JSON sie nicht unterstützt). Darüber hinaus ist es ein weitaus weniger effizienter Vorgang als derold_array.slice(0);
, der sowohl besser als auch schneller funktionieren sollte.Ich habe das Klonen eines Arrays von Objekten mit Object.assign gelöst
oder noch kürzer mit Spread-Syntax
quelle
{}
mitnew Dinosaur()
.Wenn Sie nur eine flache Kopie benötigen, ist dies ganz einfach:
quelle
0
.slice()
slice
ist ein neues Array, enthält jedoch die Verweise auf die ursprünglichen Array-Objekte.Der beste und aktuellste Weg, diesen Klon zu erstellen, ist wie folgt:
Verwendung der
...
ES6-Spread-Operators.Hier ist das einfachste Beispiel:
Auf diese Weise verteilen wir das Array in einzelne Werte und fügen es mit dem Operator [] in ein neues Array ein.
Hier ist ein längeres Beispiel, das die verschiedenen Funktionsweisen zeigt:
quelle
Das funktioniert bei mir:
Und wenn Sie eine tiefe Kopie der Objekte im Array benötigen:
quelle
quelle
JSON.parse(JSON.stringify(origArray));
JSON.parse(JSON.stringify(origArray));
ist definitiv die einfachste Lösung.Map erstellt ein neues Array aus dem alten (ohne Bezug auf das alte). Innerhalb der Map erstellen Sie ein neues Objekt und durchlaufen Eigenschaften (Schlüssel) und weisen dem neuen Objekt Werte aus dem alten Array-Objekt zu, die den entsprechenden Eigenschaften entsprechen.
Dadurch wird genau das gleiche Array von Objekten erstellt.
quelle
Möglicherweise habe ich eine einfache Möglichkeit, dies zu tun, ohne eine schmerzhafte Rekursion durchführen zu müssen und nicht alle feineren Details des betreffenden Objekts zu kennen. Konvertieren Sie mit jQuery einfach Ihr Objekt mithilfe von jQuery in JSON.
$.toJSON(myObjectArray)
Nehmen Sie dann Ihre JSON-Zeichenfolge und bewerten Sie sie zurück zu einem Objekt. BAM! Gemacht und gemacht! Problem gelöst. :) :)quelle
eval
.eval()
Am besten gar nicht verwenden. Es ist ein Sicherheitsrisiko.Ich beantworte diese Frage, weil es keine einfache und explizite Lösung für das Problem des "Klonens eines Arrays von Objekten in Javascript" zu geben scheint:
Diese Lösung iteriert die Array-Werte, iteriert dann die Objektschlüssel, speichert diese in einem neuen Objekt und verschiebt dieses neue Objekt in ein neues Array.
Siehe jsfiddle . Hinweis: Ein einfaches
.slice()
oder[].concat()
nicht genug für die Objekte innerhalb des Arrays.quelle
JQuery Extend funktioniert einwandfrei. Sie müssen lediglich angeben, dass Sie ein Array anstelle eines Objekts klonen ( beachten Sie das [] anstelle von {} als Parameter für die Extend-Methode ):
quelle
Diese Methode ist sehr einfach und Sie können Ihren Klon ändern, ohne das ursprüngliche Array zu ändern.
quelle
[...oldArray]
undoldArray.slice(0)
tun eine flache eine Ebene tiefer zu kopieren. Das ist also super nützlich, aber kein wirklich tiefer Klon.lodash.clonedeep
npm erstellt werdenWie Daniel Lew erwähnte, haben zyklische Graphen einige Probleme. Wenn ich dieses Problem hätte, würde ich entweder
clone()
den problematischen Objekten spezielle Methoden hinzufügen oder mich daran erinnern, welche Objekte ich bereits kopiert habe.Ich würde es mit einer Variablen machen,
copyCount
die sich jedes Mal um 1 erhöht, wenn Sie Ihren Code kopieren. Ein Objekt, das niedrigercopyCount
als der aktuelle Kopiervorgang ist, wird kopiert. Wenn nicht, sollte auf die bereits vorhandene Kopie verwiesen werden. Dies macht es notwendig, vom Original auf seine Kopie zu verlinken.Es gibt noch ein Problem: Speicher. Wenn Sie diese Referenz von einem Objekt zum anderen haben, kann der Browser diese Objekte wahrscheinlich nicht freigeben, da immer von irgendwoher auf sie verwiesen wird. Sie müssten einen zweiten Durchgang machen, bei dem Sie alle Kopierreferenzen auf Null setzen. (Wenn Sie dies tun, müssten Sie keinen haben,
copyCount
aber ein BoolescherisCopied
Wert würde ausreichen, da Sie den Wert im zweiten Durchgang zurücksetzen können.)quelle
Array.slice kann verwendet werden, um ein Array oder einen Teil eines Arrays zu kopieren. Http://www.devguru.com/Technologies/Ecmascript/Quickref/Slice.html Dies würde mit Zeichenfolgen und Zahlen funktionieren. - Ändern einer Zeichenfolge in Ein Array würde das andere nicht beeinflussen - aber Objekte werden immer noch nur als Referenz kopiert, sodass Änderungen an referenzierten Objekten in einem Array Auswirkungen auf das andere Array haben würden.
Hier ist ein Beispiel für einen JavaScript-Rückgängig-Manager, der hierfür hilfreich sein könnte: http://www.ridgway.co.za/archive/2007/11/07/simple-javascript-undo-manager-for-dtos.aspx
quelle
Mein Ansatz:
gibt mir einen schönen, sauberen, tiefen Klon des ursprünglichen Arrays - wobei keines der Objekte auf das Original zurück verwiesen wird :-)
quelle
lodash hat folgende
cloneDeep
Funktion:quelle
Wenn Sie einen tiefen Klon implementieren möchten, verwenden Sie JSON.parse (JSON.stringify (Ihr {} oder [])).
quelle
Vergiss eval () (ist die am häufigsten missbrauchte Funktion von JS und verlangsamt den Code) und Slice (0) (funktioniert nur für einfache Datentypen)
Dies ist die beste Lösung für mich:
quelle
Ich war ziemlich frustriert von diesem Problem. Anscheinend tritt das Problem auf, wenn Sie ein generisches Array an die Methode $ .extend senden. Um dies zu beheben, habe ich eine kleine Überprüfung hinzugefügt, die perfekt mit generischen Arrays, jQuery-Arrays und allen Objekten funktioniert.
Rufen Sie auf mit:
quelle
Dadurch werden Arrays, Objekte, Null- und andere Skalarwerte tiefgreifend kopiert und alle Eigenschaften für nicht native Funktionen tiefgreifend kopiert (was ziemlich ungewöhnlich, aber möglich ist). (Aus Effizienzgründen versuchen wir nicht, nicht numerische Eigenschaften auf Arrays zu kopieren.)
quelle
Ich verwende die neue ECMAScript 6 Object.assign- Methode:
Das erste Argument dieser Methode ist das zu aktualisierende Array. Wir übergeben ein leeres Objekt, weil wir ein neues Objekt haben möchten.
Wir können auch diese Syntax verwenden, die dieselbe ist, aber kürzer:
quelle
Wir können eine einfache rekursive Array-Methode erfinden, um mehrdimensionale Arrays zu klonen. Während die Objekte in den verschachtelten Arrays ihren Verweis auf die entsprechenden Objekte im Quellarray beibehalten, werden Arrays dies nicht tun.
quelle
In JavaScript ändern Array- und Objektkopien die Ursprungswerte, daher ist Deep Copy die Lösung dafür.
Eine tiefe Kopie bedeutet, tatsächlich ein neues Array zu erstellen und über die Werte zu kopieren, da alles, was damit passiert, niemals den ursprünglichen beeinflusst.
JSON.parse
undJSON.stringify
ist der beste und einfachste Weg zum Deep Copy. DieJSON.stringify()
Methode konvertiert einen JavaScript-Wert in eine JSON-Zeichenfolge. DieJSON.parse()
Methode analysiert eine JSON-Zeichenfolge und erstellt den durch die Zeichenfolge beschriebenen JavaScript-Wert oder das Objekt.// Deep Clone
Für weitere Details: Lesen Sie hier
quelle
mit jQuery:
quelle
Der folgende Code führt rekursiv ein tiefes Kopieren von Objekten und Arrays durch :
Quelle
quelle
arguments.callee
ist im strengen Modus nicht verfügbar und hat ansonsten Leistungsprobleme.Einige elegante Möglichkeiten zum tiefen Klonen in Javascript
https://mootools.net/core/docs/1.6.0/Types/Object
https://scotch.io/bar-talk/copying-objects-in-javascript
1) Eine Vanille-Javascript-Methode zum Klonen von Objekten
2) Ein cleverer Exploit der JSON-Bibliothek zum Deep-Clone von Objekten
3) Verwenden der $ .extend () -Funktion von jQuery
4) Verwenden der clone () -Funktion von Mootools zum Klonen von Objekten
quelle
Ich denke, es ist gelungen, eine generische Methode zum Deep Cloning von JavaScript-Strukturen zu schreiben, die hauptsächlich von
Object.create
allen modernen Browsern unterstützt wird. Der Code lautet wie folgt:quelle
Object.create
wirditem
als Prototyp des Objekts behandelt , aber das unterscheidet sich vom Klonen. Wennitem
es geändert wird, werden Änderungen in seinem "Klon" wiedergegeben und umgekehrt. Dieser Ansatz funktioniert nicht.Zum Klonen der Objekte wollte ich nur ECMAScript 6 vorschlagen
reduce()
:Aber ehrlich gesagt gefällt mir die Antwort von @dinodsaurus noch besser. Ich stelle diese Version hier nur als weitere Option ein, aber ich persönlich werde sie verwenden,
map()
wie von @dinodsaurus vorgeschlagen.quelle
Je nachdem, ob Sie Underscore oder Babel haben, finden Sie hier einen Benchmark für die unterschiedliche Art des Deep Cloning eines Arrays.
https://jsperf.com/object-rest-spread-vs-clone/2
Sieh aus, als wäre Babel am schnellsten.
quelle
quelle