.clone() vs. Kopierkonstruktoren.clone()-MethodenIn diesem Kapitel betrachten wir zwei Techniken zur Implementierung des Kopierens von Klasseninstanzen
.clone()-Methoden.clone()-MethodenDiese Technik führt eine Methode .clone() pro Klasse ein, deren Instanzen kopiert werden sollen. Sie gibt eine tiefe Kopie von this zurück. Das folgende Beispiel zeigt drei Klassen, die geklont werden können.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
clone() {
return new Point(this.x, this.y);
}
}
class Color {
constructor(name) {
this.name = name;
}
clone() {
return new Color(this.name);
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y);
this.color = color;
}
clone() {
return new ColorPoint(
this.x, this.y, this.color.clone()); // (A)
}
}Zeile A demonstriert einen wichtigen Aspekt dieser Technik: zusammengesetzte Instanzeigenschaftswerte müssen ebenfalls rekursiv geklont werden.
Ein Kopierkonstruktor ist ein Konstruktor, der eine weitere Instanz der aktuellen Klasse verwendet, um die aktuelle Instanz einzurichten. Kopierkonstruktoren sind in statischen Sprachen wie C++ und Java beliebt, wo Sie über statische Überladung mehrere Versionen eines Konstruktors bereitstellen können. Hier bedeutet statisch, dass die Wahl, welche Version verwendet werden soll, zur Kompilierzeit getroffen wird.
In JavaScript müssen wir diese Entscheidung zur Laufzeit treffen, und das führt zu uneleganten Code
class Point {
constructor(...args) {
if (args[0] instanceof Point) {
// Copy constructor
const [other] = args;
this.x = other.x;
this.y = other.y;
} else {
const [x, y] = args;
this.x = x;
this.y = y;
}
}
}So würden Sie diese Klasse verwenden
const original = new Point(-1, 4);
const copy = new Point(original);
assert.deepEqual(copy, original);Statische Factory-Methoden sind eine Alternative zu Konstruktoren und funktionieren in diesem Fall besser, da wir die gewünschte Funktionalität direkt aufrufen können. (Hier bedeutet statisch, dass diese Factory-Methoden Klassenmethoden sind.)
Im folgenden Beispiel haben die drei Klassen Point, Color und ColorPoint jeweils eine statische Factory-Methode .from()
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static from(other) {
return new Point(other.x, other.y);
}
}
class Color {
constructor(name) {
this.name = name;
}
static from(other) {
return new Color(other.name);
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y);
this.color = color;
}
static from(other) {
return new ColorPoint(
other.x, other.y, Color.from(other.color)); // (A)
}
}In Zeile A kopieren wir wieder rekursiv.
So funktioniert ColorPoint.from()
const original = new ColorPoint(-1, 4, new Color('red'));
const copy = ColorPoint.from(original);
assert.deepEqual(copy, original);