Eine kurze Diskussion über Shallow Copy und Deep Copy in JavaScript

Eine kurze Diskussion über Shallow Copy und Deep Copy in JavaScript

Im Internet gibt es viele Diskussionen zu diesem Thema. Ich habe sie je nach Situation selbst sortiert. Am Ende konnte ich eine nahezu perfekte Deep Copy erstellen. Jeder ist herzlich eingeladen, mitzudiskutieren.

Objekte in javascript sind Referenztypen. Beim Kopieren von Objekten müssen Sie überlegen, ob Sie Shallow Copy oder Deep Copy verwenden möchten.

1. Direkte Zuordnung

Ein Objekt ist ein Referenztyp. Wird es direkt einem anderen Objekt zugewiesen, handelt es sich lediglich um eine Referenz. Tatsächlich verweisen die beiden Variablen auf dasselbe Datenobjekt. Ändern sich die Eigenschaften eines Objekts, ändern sich auch die Eigenschaften des anderen.

Beispiel 1, einfaches Beispiel:

lass Mensch1 = {
    ID: 1,
    Name: "glücklich"
};
human2 = human1; // Hier ist eine direkte Zuweisung console.log(human1); // {id: 1, name: 'happy'}
console.log(human2); // {id: 1, name: "glücklich"}
 
// Wenn der Name von human1 geändert wird, wird auch der von human2 geändert human1.name = "life";
console.log(Mensch1); // {id: 1, name: 'Leben'}
console.log(human2); // {id: 1, name: 'leben'}

Beispiel 2: Durch die Übergabe eines Objekts als Parameter wird auch eine Referenz übergeben:

lass Mensch1 = {
    ID: 1,
    Name: "glücklich"
};
 
console.log(Mensch1); // {id: 1, name: "glücklich"}
 
Funktion foo(Mensch) {
    // Hier wird der Name des menschlichen Objektes geändert human.name = "life";
}
foo(human1); // die Übergabe eines Objekts erfolgt per Referenz console.log(human1); // {id: 1, name: 'life'}

2. Oberflächliche Kopie

Bei einer oberflächlichen Kopie wird nur die erste Ebene des Objekts kopiert. Wenn der Eigenschaftswert der ersten Ebene ein Objekt ist, wird nur ein Verweis auf die Eigenschaft kopiert.

lass Objekt1 = {
    ein: 1,
    b: { // b ist ein Objekt b1: 2
    }
};
object2 = Object.assign({}, object1); // Dies ist eine oberflächliche Kopie, bei der nur die Referenz von Objekt b kopiert wird // a ist ein regulärer Typ und beeinflusst sich nicht gegenseitig object1.a = 10;
konsole.log(objekt1.a); // 10
konsole.log(Objekt2.a); // 1
 
// b ist ein Objekt, das sich gegenseitig beeinflusst object1.b.b1 = 20;
konsole.log(objekt1.b.b1); // 20
konsole.log(objekt2.b.b1); // 20


Wenn Sie eine vollständige Kopie erreichen möchten, müssen Sie eine tiefe Kopie verwenden.

3. Tiefe Kopie

Sen-Kopie bedeutet, dass nicht nur eine Ebene kopiert werden muss, sondern auch die darin enthaltenen Ebenen (sofern es sich um Objekte handelt) kopiert werden müssen.

1. JSON-Objektmethode

Wenn bestätigt werden kann, dass es sich bei dem Objekt um ein JSON Objekt handelt, kann es im JSON Objektformat verwendet werden.

Verwenden Sie das obige Beispiel:

lass Objekt1 = {
    ein: 1,
    b: { // b ist ein Objekt b1: 2
    }
};
 
object2 = JSON.parse(JSON.stringify(object1)); // Tiefe Kopie // a ist ein regulärer Typ und beeinflusst sich nicht gegenseitig object1.a = 10;
konsole.log(objekt1.a); // 10
konsole.log(objekt2.a); // 1
 
// b ist ein Objekt und beeinflusst sich nicht gegenseitig object1.b.b1 = 20;
konsole.log(objekt1.b.b1); // 20
konsole.log(Objekt2.b.b1); // 2


Das Prinzip der tiefen Kopie besteht hier eigentlich darin, das Objekt zuerst in eine json Zeichenfolge und dann in json Objekt umzuwandeln. Nach der Umwandlung in eine json Zeichenfolge hat es nichts mehr mit dem ursprünglichen Objekt zu tun.

Vorteile dieser Methode: Sie ist sehr einfach umzusetzen.

Mangel:

Wenn ein Attributwert eine Funktion ist, kann er nicht kopiert werden und die Daten gehen verloren.
Darüber hinaus können Prototypobjekte nicht kopiert werden.

Daher ist diese Methode nur für Objekte geeignet, bei denen bestätigt ist, dass es sich um reine json -Daten handelt.

2. Rekursives Kopieren

Da wir Schicht für Schicht kopieren müssen, ist es einfach, über einen rekursiven Ansatz nachzudenken. Siehe die folgende Implementierung:

Funktion deepCopy(Quelle) {
    // Wenn es kein Objekt oder null ist, direkt zurückgeben, if (typeof source !== 'object' || source === null) {
        Rücklaufquelle;
    }
 
    lass Ziel = {};
    // Eigenschaften durchlaufen und kopieren für (let k in source) {
        wenn (!source.hasOwnProperty(k)) {
            weitermachen;
        }
 
        if (typeof source[k] === 'object') { // Wenn es ein Objekt ist, rekursiv kopieren target[k] = deepCopy(source[k]);
            weitermachen;
        }
 
        let descriptor = Object.getOwnPropertyDescriptor(Quelle, k);
        Objekt.defineProperty(Ziel, k, Deskriptor);
    }
 
    Rücklaufziel;
}

Da die Objekte Schicht für Schicht kopiert werden, beeinflussen sich die beiden Objekte nach Abschluss des Kopiervorgangs nicht gegenseitig und Methoden können auch unterstützt werden.

lass Objekt1 = {
    ein: 1,
    b: { // b ist ein Objekt b1: 2
    },
    f: function() { // f ist eine Methode console.log(3);
    }
};
object2 = deepCopy(object1); // Deep Copy, Sie können auch Funktionen kopieren.
objekt1.f(); // 3
objekt2.f(); // 3
 
// b ist ein Objekt und beeinflusst sich nicht gegenseitig object1.b.b1 = 20;
konsole.log(objekt1.b.b1); // 20
konsole.log(Objekt2.b.b1); // 2


Prototypobjekte kopieren

Bei dieser Methode gibt es jedoch immer noch ein Problem, nämlich, dass das Prototypobjekt nicht kopiert werden kann. Lassen Sie es uns ein wenig verbessern:

// Ändern Sie let target = {}; wie folgt // um sicherzustellen, dass der Prototyp auch kopiert wird let target = Object.create(Object.getPrototypeOf(source));


Das ist alles. Lassen Sie es uns anhand eines Beispiels überprüfen:

Funktion Mensch() {
    diese.id = 1;
}
Mensch.prototype.bar = Funktion() {
    console.log("Leiste");
};
 
let Mensch1 = neuer Mensch();
Mensch2 = tiefe Kopie (Mensch1);
 
konsole.log("Mensch1", Mensch1);
Konsole.log("Mensch2", Mensch2);


Schauen Sie sich die Prototypen der nächsten beiden Objekte an:

Vollständige Kopie des Prototypobjekts:

Perfekte Kopie.

Natürlich gibt es bei dieser Methode ein Problem: Wenn die Rekursionsebene zu tief ist, kann es leicht zu einem Stapelüberlauf kommen. Allerdings empfiehlt es sich in der Praxis auch, sehr große Objekte nicht zu kopieren, hier gibt es sicher auch andere gute Lösungen.

Dies ist das Ende dieses Artikels über Shallow Copy und Deep Copy JavaScript . Weitere relevante Inhalte zu Shallow Copy und Deep Copy in JavaScript finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Referenzdokumente:

JS implementiert Deep Copy: https://www.cnblogs.com/dobeco/p/11295316.html
Object.assign(): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Objekt.erstellen(): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/erstellen
Object.getPrototypeOf(): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf
Object.defineProperty(): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Object.getOwnPropertyDescriptor(): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
hasOwnProperty(): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung von Deep Copy und Shallow Copy in JavaScript
  • Detaillierte Beschreibung von Shallow Copy und Deep Copy in js
  • Detaillierte Erläuterung der Deep Copy und Shallow Copy im JS-Variablenspeicher
  • Kopieren von JS-Objekten (Deep Copy und Shallow Copy)
  • Alltägliche Diskussionen über Deep Copy und Shallow Copy in JavaScript

<<:  MySQL Infobright-Installationsschritte

>>:  Fünf Lösungen für Cross-Browser-Probleme (Zusammenfassung)

Artikel empfehlen

Grundsätze für die Bereitstellung und Konfiguration mehrerer Tomcat-Instanzen

1. Schalten Sie die Firewall aus und übertragen S...

So bedienen Sie das Kontrollkästchen auf einer HTML-Seite

Kontrollkästchen sind auf Webseiten sehr verbreit...

Die Darstellung und Öffnungsmethode eines Hyperlinks

<br />Verwandte Artikel: So rufen Sie einen ...

Detaillierte Erläuterung der langsamen MySQL-Protokollabfrage

Langsame Protokollabfragefunktion Die Hauptfunkti...

Detaillierte Installation und Verwendung der Virtuoso-Datenbank unter Linux

Ich habe kürzlich einige Dinge zu verknüpften Dat...

Tutorial zur HTML-Tabellenauszeichnung (37): Hintergrundbild-Attribut BACKGROUND

Legen Sie das Hintergrundbild für die Tabellenübe...

MySQL REVOKE zum Löschen von Benutzerberechtigungen

In MySQL können Sie mit der REVOKE-Anweisung best...

MySQL 5.6.37 (zip) Download Installationskonfiguration Grafik-Tutorial

In diesem Artikel finden Sie das Download-, Insta...

Allgemeine Befehle für MySQL-Autorisierung, Start und Dienststart

1. Vier Startmethoden: 1.mysqld Starten Sie den M...

So installieren und verwenden Sie Cockpit unter CentOS 8/RHEL 8

Cockpit ist ein webbasiertes Serververwaltungstoo...

So autorisieren Sie Remoteverbindungen in MySQL unter Linux

Hinweis: Andere Maschinen (IP) können ohne Autori...