Da Objekte in JavaScript Referenzwerte sind, können Sie nicht einfach mit der =
kopieren. Aber keine Sorge, hier sind 3 Möglichkeiten für Sie, ein Objekt zu klonen 👍
# Objekte sind Referenztypen
Ihre erste Frage könnte sein, warum kann ich nicht =
. Mal sehen, was passiert,wenn wir das tun:
const obj = { one: 1, two: 2 };const obj2 = obj;console.log( obj, // {one: 1, two: 2}; obj2, // {one: 1, two: 2};);
Bisher scheinen beide Objekte dasselbe auszugeben. Also kein problem, richtig., Aber mal sehen, was passiert, wenn wir unser zweites Objekt bearbeiten:
const obj2.three = 3;console.log(obj2);// {one: 1, two: 2, three: 3}; <-- ✅console.log(obj);// {one: 1, two: 2, three: 3}; <-- 😱
WTH?! Ich habe obj2
aber warum war obj
ebenfalls betroffen? Das liegt daran, dass Objekte Referenztypen sind. Wenn Sie also =
, wird der Zeiger auf den belegten Speicherplatz kopiert. Referenztypen enthalten keine Werte, sie sind ein Zeiger auf den Wert im Speicher.
Wenn Sie mehr darüber erfahren möchten, schauen Sie sich Gordons Zhu Watch and Code Course an. Es ist kostenlos, sich anzumelden und das Video „Vergleich mit Objekten“anzusehen., Er gibt eine super tolle Erklärung dazu.
# 1. Mit Spread
Mit spread wird Ihr Objekt geklont. Beachten Sie, dass dies eine flache Kopie sein wird. Ab diesem Beitrag befindet sich der Spread-Operator zum Klonen von Objekten in Stufe 4. Es ist also noch nicht offiziell in den Spezifikationen. Wenn Sie dies verwenden würden, müssten Sie es mit Babel (oder ähnlichem) kompilieren.
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = { ...food };console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# 2. Objekt verwenden.assign
Alternativ Object.assign
ist in der offiziellen Version und wird auch eine flache Kopie des Objekts erstellen.,
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = Object.assign({}, food);console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
Beachten Sie als erstes Argument die leere {}
Dadurch wird sichergestellt, dass Sie das ursprüngliche Objekt nicht mutieren 👍
# 3. Wenn Sie JSON
Auf diese Weise verwenden, erhalten Sie eine tiefe Kopie. Jetzt werde ich erwähnen, dies ist eine schnelle und schmutzige Art, ein Objekt tief zu klonen. Für eine robustere Lösung, die ich empfehlen würde, mit so etwas wie lodash
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = JSON.parse(JSON.stringify(food));console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# Lodash DeepClone vs JSON
Hier ist ein Kommentar aus der community. Ja, es war für meinen vorherigen Beitrag, Wie man ein Array tief klont ., Aber die Idee gilt immer noch für Objekte.
Alfredo Salzillo: Ich möchte Sie darauf hinweisen, dass es einige Unterschiede zwischen deepClone und JSON gibt.stringify/analysieren.
- JSON.stringify / parse funktioniert nur mit Number und String und Object Literal ohne Funktions – oder Symboleigenschaften.
- deepClone arbeiten mit allen Typen, Funktion und Symbol werden als Referenz kopiert.
Hier ist ein Beispiel:
@OlegVaraksin : Die JSON-Methode hat Probleme mit zirkulären Abhängigkeiten. Weiterhin kann die Reihenfolge der Eigenschaften im geklonten Objekt unterschiedlich sein.,
# Flacher Klon vs tiefer Klon
Als ich spread ...
zum Kopieren eines Objekts verwendete, erstelle ich nur eine flache Kopie. Wenn das Array verschachtelt oder mehrdimensional ist, funktioniert es nicht. Hier ist unser Beispiel, das wir verwenden werden:
# Flache Kopie
Klonen wir unser Objekt mit spread:
const shallowClone = { ...nestedObject };// Changed our cloned objectshallowClone.flag = '🇹🇼';shallowClone.country.city = 'taipei';
Also haben wir unser geklontes Objekt geändert, indem wir die Stadt geändert haben. Mal sehen, die Ausgabe.
console.log(shallowClone);// {country: '🇹🇼', {city: 'taipei'}}console.log(nestedObject);// {country: '🇨🇦', {city: 'taipei'}} <-- 😱
Eine flache Kopie bedeutet, dass die erste Ebene kopiert und auf tiefere Ebenen verwiesen wird.,
# Deep Copy
Nehmen wir dasselbe Beispiel, aber das Anwenden einer Deep Copy mit „JSON“
Wie Sie sehen, ist die Deep copy eine echte Kopie für verschachtelte Objekte. Oft ist eine flache Kopie gut genug, Sie brauchen keine tiefe Kopie. Es ist wie eine Nagelpistole gegen einen Hammer. Die meiste Zeit ist der Hammer vollkommen in Ordnung. Mit einer Nagelpistole für einige kleine Kunst und Handwerk ist oft nur ein Overkill, ein Hammer ist in Ordnung. Es geht darum, das richtige Werkzeug für den richtigen Job zu verwenden 🤓
# Performance
Leider kann ich keinen Test für Spread schreiben, da er noch nicht offiziell in der Spezifikation enthalten ist., Trotzdem habe ich es in den Test aufgenommen, damit Sie es in Zukunft 😝ausführen können. Das Ergebnis zeigt jedoch, dass Object.assign
viel schneller ist als JSON
.
Leistungstest
# Community Input
# Objekt.weisen Sie vs Spread
@d9el zu: Es ist wichtig, dieses Objekt zu beachten.assign ist eine Funktion, die das Zielobjekt ändert und zurückgibt. In Samanthas Beispiel, das Folgendes verwendet,
const cloneFood = Object.assign({}, food);
{}
ist das Objekt, das geändert wird., Das Zielobjekt wird zu diesem Zeitpunkt von keiner Variablen referenziert, aber da Object.assign
das Zielobjekt zurückgibt, können wir das resultierende zugewiesene Objekt in der Variablen cloneFood
speichern. Wir könnten unser Beispiel umstellen und Folgendes verwenden:
const food = { beef: '🌽', bacon: '🥓' };Object.assign(food, { beef: '🥩' });console.log(food);// { beef: '🥩', bacon: '🥓' }
Offensichtlich ist der Wert von beef
in unserem Lebensmittelobjekt falsch, sodass wir mit Object.assign
den richtigen Wert von beef
zuweisen können., Wir verwenden den zurückgegebenen Wert der Funktion überhaupt nicht, aber wir ändern unser Zielobjekt, auf das wir mit const .
Spread hingegen ist ein Operator, der Eigenschaften eines Objekts in ein neues Objekt kopiert., Wenn wir das obige Beispiel mit spread replizieren möchten, um unsere Variable zu ändern food...
const food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};// TypeError: invalid assignment to const `food'
...
Wir erhalten einen Fehler, da wir spread beim Erstellen neuer Objekte verwenden und daher ein ganz neues Objekt zuweisen, das mit
, was illegal ist., Wir können also entweder eine neue Variable deklarieren, in der sich unser neues Objekt befindet, wie folgt:
const food = { beef: '🌽', bacon: '🥓' };const newFood = { ...food, beef: '🥩',};console.log(newFood);// { beef: '🥩', bacon: '🥓' }
oder wir könnten mit let
oder var
deklarieren, wodurch wir ein ganz neues Objekt zuweisen können:
let food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};console.log(food);// { beef: '🥩', bacon: '🥓' }
Danke: @d9el
# Deep Clone mit externen Bibliotheken
# Weitere Möglichkeiten zur Verwendung von JavaScript
- @hariharan_d3v :
Object.fromEntries(Object.entries(food))
klont das Objekt.
Schreibe einen Kommentar