Wie klone ich eine Javascript-Klasseninstanz mit ES6?
Ich bin nicht an Lösungen interessiert, die auf jquery oder $ expand basieren.
Ich habe ziemlich alte Diskussionen über das Klonen von Objekten gesehen, die darauf hindeuten, dass das Problem ziemlich kompliziert ist, aber mit ES6 bietet sich eine sehr einfache Lösung an - ich werde es unten darlegen und sehen, ob die Leute es für zufriedenstellend halten.
edit: Es wird vorgeschlagen, dass meine Frage ein Duplikat ist. Ich habe diese Antwort gesehen, aber sie ist 7 Jahre alt und beinhaltet sehr komplizierte Antworten mit js vor ES6. Ich schlage vor, dass meine Frage, die ES6 ermöglicht, eine dramatisch einfachere Lösung hat.
Object
Daten, die als Dateninhaber verwendet wurden. Hier geht es um ES6class
es und das Problem, die Klassentypinformationen nicht zu verlieren. Es braucht eine andere Lösung.Antworten:
Es ist kompliziert. Ich habe viel versucht, am Ende funktionierte dieser Einzeiler für meine benutzerdefinierten ES6-Klasseninstanzen:
Es vermeidet, den Prototyp zu setzen, weil sie sagen , es den Code verlangsamt viel.
Es unterstützt Symbole, ist jedoch nicht perfekt für Getter / Setter und funktioniert nicht mit nicht aufzählbaren Eigenschaften (siehe Object.assign () -Dokumente ). Außerdem scheint das Klonen grundlegender interner Klassen (wie Array, Datum, RegExp, Map usw.) leider häufig eine individuelle Behandlung zu erfordern.
Fazit: Es ist ein Chaos. Hoffen wir, dass es einmal eine native und saubere Klonfunktionalität geben wird.
quelle
Beachten Sie die Eigenschaften von Object.assign : Es wird eine flache Kopie erstellt und keine Klassenmethoden kopiert.
Wenn Sie eine tiefe Kopie oder mehr Kontrolle über die Kopie wünschen, gibt es die Funktionen des lodash-Klons .
quelle
Object.create
erstellt neues Objekt mit angegebenen Prototyp, warum nicht dann einfachconst clone = Object.assign(Object.create(instanceOfBlah), instanceOfBlah)
. Auch Klassenmethoden werden kopiert.Blah.prototype != instanceOfBlah
. Sie sollten verwendenObject.getPrototypeOf(instanceOfBlah)
Es wird nicht empfohlen, Erweiterungen des Prototyps vorzunehmen. Dies führt zu Problemen, wenn Sie Tests an Ihrem Code / Ihren Komponenten durchführen. Die Unit-Test-Frameworks übernehmen nicht automatisch Ihre Prototyp-Erweiterungen. Es ist also keine gute Praxis. Weitere Erklärungen zu Prototypenerweiterungen finden Sie hier. Warum ist das Erweitern nativer Objekte eine schlechte Praxis?
Das Klonen von Objekten in JavaScript ist nicht einfach oder unkompliziert. Hier ist die erste Instanz, die "Shallow Copy" verwendet:
1 -> Flacher Klon:
Ergebnisse:
Hinweis: Wenn die Instanz Verschlüsse als eigene Eigenschaften hat, wird sie von dieser Methode nicht umbrochen. ( Lesen Sie mehr über Schließungen ) Außerdem wird das Unterobjekt "Adresse" nicht geklont.
wird nicht funktionieren.
funktioniert, da der Klon auch seine Prototypen kopiert.
So klonen Sie Arrays mit Object.assign:
Klonen Sie das Array mit ECMAScript Spread Sintax:
2 -> Deep Clone:
Um eine völlig neue Objektreferenz zu archivieren, können Sie JSON.stringify () verwenden, um das ursprüngliche Objekt als Zeichenfolge zu analysieren und es anschließend wieder in JSON.parse () zu analysieren.
Bei Deep Clone bleiben die Adressverweise erhalten. Die deepClone-Prototypen werden jedoch verloren gehen, daher funktioniert deepClone.logFullName () nicht.
3 -> Bibliotheken von Drittanbietern:
Eine weitere Option ist die Verwendung von Bibliotheken von Drittanbietern wie Loadash oder Unterstrich. Sie erstellen ein neues Objekt und kopieren jeden Wert vom Original in das neue Objekt, wobei die Referenzen im Speicher bleiben.
Unterstrich: let cloneUnderscore = _ (original) .clone ();
Loadash-Klon: var cloneLodash = _.cloneDeep (original);
Der Nachteil von lodash oder Unterstrich war die Notwendigkeit, einige zusätzliche Bibliotheken in Ihr Projekt aufzunehmen. Sie sind jedoch gute Optionen und führen auch zu Hochleistungsergebnissen.
quelle
{}
erbt der Klon keine der Prototypmethoden des Originals.clone.logFullName()
wird überhaupt nicht funktionieren. Das, wasObject.assign( Object.create(Object.getPrototypeOf(eOriginal)), eOriginal)
du vorher hattest, war in Ordnung. Warum hast du das geändert?Object.assign({},original)
so funktioniert es nicht.Ein weiterer Liner:
Die meiste Zeit ... (funktioniert für Date, RegExp, Map, String, Number, Array), übrigens, Klonen von String, Nummer ist ein bisschen lustig.
für Klassen ohne Kopierkonstruktor:
quelle
quelle
Sie können den Spread-Operator verwenden, wenn Sie beispielsweise ein Objekt mit dem Namen Obj klonen möchten:
Und wenn Sie dem geklonten Objekt etwas ändern oder hinzufügen möchten:
quelle