Wie erhalte ich eine perfekte tiefe Kopie in JavaScript?

Erzielen Sie eine nahezu perfekte tiefe Kopie von etwa 20 Zeilen

Foto von Hello I'm Nik auf Unsplash

Vorwissen

Datentypen in Javascript können in Primitivwerttypen und Referenzwerttypen unterteilt werden. Wenn wir Datenoperationen durchführen, werden sie einige Unterschiede aufweisen.

let primitiveValue = 1;
const copyPrimitiveValue = primitiveValue;
primitiveValue = 2;
console.log('primitiveValue: ', primitiveValue); // 2
console.log('copyPrimitiveValue: ', copyPrimitiveValue); // 1
const referenceValue = { value: 1 };
const copyReferenceValue = referenceValue;
referenceValue.value = 2;
console.log('referenceValue: ', referenceValue); // { value: 2 }
console.log('copyReferenceValue: ', copyReferenceValue); // { value: 2 }

Wie oben erwähnt, können Datentypen in zwei Typen unterteilt werden. Primitive Werttypen umfassen undefined, null, number, string, boolean, symbol und bigint; Zu den Referenzwerttypen gehören von Object abgeleitete Array-Objekte, Funktionsobjekte usw. Primitive Werttypen werden direkt auf dem Stack gespeichert, während Referenzwerttypen auf dem Heap gespeichert werden und eine auf dem Stack gespeicherte Adresse darauf zeigt.

Auf diese Weise können wir das obige Phänomen erklären. Für den ursprünglichen Werttyp wird eine Kopie direkt kopiert, und für den Referenzwerttyp wird eine Adresse kopiert, wodurch sowohl referenceValue als auch copyReferenceValue auf dasselbe Datenelement auf dem Heap zeigen. Mit anderen Worten, beide Adressen können dieselben Daten auf dem Heap ändern.

Flache Kopie

Eine flache Kopie bedeutet, dass nur eine Ebene des Objekts kopiert wird und die tiefe Ebene des Objekts direkt eine Adresse kopiert. Es gibt viele native Methoden in Javascript, die flache Kopien sind. Zum Beispiel mit Object.assignAPI oder dem Spread-Operator.

const target = {};
const source = { a: { b: 1 }, c: 2 };
Object.assign(target, source);
source.a.b = 3;
source.c = 4;
console.log(source); // { a: { b: 3 }, c: 4 }
console.log(target); // { a: { b: 3 }, c: 2 }
// Same effect as Object.assign
const target1 = { ...source };

Deep Copy bedeutet das Klonen von zwei identischen Objekten, jedoch ohne Verbindung zueinander.

1. JSON.stringify-API

const source = { a: { b: 1 } };
const target = JSON.parse(JSON.stringify(source));
source.a.b = 2;
console.log(source); // { a: { b: 2 } };
console.log(target); // { a: { b: 1 } };

2. Fast perfekte tiefe Kopie

Der obige Code ist das Endergebnis, lassen Sie mich erklären, wie es dazu kam.

  1. Zunächst verwenden wir WeakMap als Hash-Tabelle, um das Zirkelverweisproblem zu lösen, wodurch Speicherlecks effektiv verhindert werden können. Sie können die Beschreibung von WeakMap auf MDN überprüfen .
  2. Für die speziellen Typen Date und RegExp wird direkt eine neue Instanz erzeugt und zurückgegeben.
  3. Verwenden Sie Object.getOwnPropertyDescriptors, um alle Eigenschaftsbeschreibungen des aktuellen Objekts abzurufen, und verwenden Object.getPrototypeOfSie , um den Prototyp des aktuellen Objekts abzurufen. Übergeben dieser beiden Elemente als Argumente an die Object.createAPI, um ein neues Objekt mit demselben Prototyp und denselben Eigenschaften zu erstellen.
  4. Wird verwendet Reflect.ownKeys, um alle Eigenschaften des aktuellen Objekts zu durchlaufen, einschließlich nicht aufzählbarer Eigenschaften und Symboleigenschaften sowie normaler Eigenschaften. Auf diese Weise kann der tiefsitzende Wert in der Schleife und Rekursion kontinuierlich in das aktuelle neue Objekt kopiert werden.
  5. Bei der Schleifenbeurteilung werden, abgesehen davon, dass die Funktion direkt zugewiesen wird, die anderen durch Rekursion neu kopiert.

const symbolKey = Symbol('symbolKey');
const originValue = {
  num: 0,
  str: '',
  boolean: true,
  unf: void 0,
  nul: null,
  obj: { name: 'object', id: 1 },
  arr: [0, 1, 2],
  func() {
    console.log('function');
  },
  date: new Date(0),
  reg: new RegExp('/regexp/ig'),
  [symbolKey]: 'symbol',
};
Object.defineProperty(originValue, 'innumerable', {
  // writable is true to ensure that the assignment operator can be used
  writable: true,
  enumerable: false,
  value: 'innumerable',
});
// Create circular reference
originValue.loop = originValue;
// Deep Copy
const clonedValue = deepClone(originValue);
// Change original value
originValue.arr.push(3);
originValue.obj.name = 'newObject';
// Remove circular reference
originValue.loop = '';
originValue[symbolKey] = 'newSymbol';
console.log('originValue: ', originValue);
console.log('clonedValue: ', clonedValue);

      

3. strukturierte Klon-API

Danke an Andrew Wooldridge für die Erwähnung der structuredCloneAPI im Antwortbereich. Ich habe festgestellt, dass es Deep Copy nativ implementieren kann, aber es kann nur den strukturiert klonbaren Typ klonen . Funktionsobjekte können beispielsweise nicht geklont werden und lösen eine DataCloneError-Ausnahme aus. Es klont auch keine Setter, Getter und ähnliche Metadaten-ähnliche Funktionen.

Es ist eine sehr neue API, wir können uns auf ihre zukünftige Entwicklung freuen. Es wurde in der Chrome 98-Version unterstützt, Sie können die Verwendung auf MDN und die Kompatibilität auf caniuse überprüfen .

Das ist es, großartig, nicht wahr? In diesem Stadium ermöglicht uns die Verwendung von Option 2, eine nahezu perfekte tiefe Kopie in Javascript zu haben.

Das ist alles für heute. Ich bin Zachary und ich werde weiterhin Geschichten über die Webentwicklung veröffentlichen. Wenn Sie solche Geschichten mögen und mich unterstützen möchten, ziehen Sie bitte in Betracht, Medium-Mitglied zu werden . Es kostet $5 pro Monat und gibt Ihnen unbegrenzten Zugriff auf Medium-Inhalte. Ich bekomme eine kleine Provision, wenn du dich über meinen Link anmeldest .

Ihre Unterstützung ist mir sehr wichtig – vielen Dank.

Suggested posts

Der Soloauftritt des rothaarigen Mädchens

Im Auftrag von Hayden filmt Katie sich selbst beim Masturbieren.

Der Soloauftritt des rothaarigen Mädchens

Es war nach Mitternacht, als Hayden Katie nach ihrem gemeinsamen Abend zurück in ihren Studentenwohnheim fuhr. Sie hatte morgens einen frühen Unterricht und hatte keine Kleidung mehr zum Wechseln, nachdem sie die Nacht zuvor bei ihm übernachtet hatte.

Medien neu denken: McChesneys fünf Wahrheiten und die Zukunft der Kommunikation

In der heutigen hypervernetzten Welt spielen Mediensysteme eine entscheidende Rolle bei der Bildung der öffentlichen Meinung und damit bei der demokratischen Entscheidungsfindung. In seiner tiefgreifenden Analyse der politischen Ökonomie der Kommunikation stellt der Wissenschaftler Robert McChesney die herkömmliche Meinung in Frage und präsentiert die „fünf Wahrheiten“ über die Medien, wie er sie nennt.

Related posts

Die „Learning at Work Week“ ist wichtiger als Sie denken

Die „Learning at Work Week“ ist wichtiger als Sie denken

Es fällt uns oft schwer, das umzusetzen, von dem wir wissen, dass es gut für uns ist. Von der Aussage, dass wir einen Lebensgefährten lieben, bis hin zur Erinnerung daran, wie ein Pirat zu reden – es wird immer diejenigen geben, die behaupten, dass ein Tag, eine Woche oder ein Monat voller Ereignisse nicht nötig sei, weil sie diese Dinge bereits tun.

Der Mord an Jordan Neely und das Problem des „patriotischen“ Rassismus

Können die USA den entscheidenden Schritt tun, rassistisches Verhalten nicht mit der Identität eines guten Amerikaners gleichzusetzen?

Der Mord an Jordan Neely und das Problem des „patriotischen“ Rassismus

[Alarm auslösen: Dieser Aufsatz enthält Screenshots von Menschen, die den Mörder von Jordan Neely loben.] Polizeibeamte haben endlich – und vielleicht widerstrebend – Daniel Penny, den Mann, der Jordan Neely bis zu seinem Tod gewürgt hat, wegen dieses Mordes angeklagt.

Zeitschrift Ouvert

Zeitschrift Ouvert

Offenes Tagebuch: Ein Bild pro Tag. Geschichten haben mich schon immer fasziniert.

Wie man den Planeten rettet und Geld verdient

Wie man den Planeten rettet und Geld verdient

Wie oft haben Sie ohne nachzudenken eine Plastikflasche, ein Glas, eine Aluminiumdose oder ein Öko-Energiepaket weggeworfen? Wie oft haben Sie sich gewünscht, dass Sie für das Recycling etwas zurückbekommen könnten? Wenn Sie wie die meisten Menschen sind, lautet die Antwort wahrscheinlich „vielfach“. Recycling wird oft als Ärger, lästige Pflicht oder Pflicht angesehen, die keinen unmittelbaren oder greifbaren Nutzen bringt.