Hallo Franz,
du hast recht, in den Einstiegsartikeln zu Objekten findet man das nicht. Ich bin aber sicher, irgendwo mal geschrieben zu haben, dass Objekte und Arrays nur Verweise auf interne Strukturen sind und die Zuweisung eines Objektes von a nach b nur den Verweis kopiert. Ich find's nur grad nicht wieder. Wie soll es da ein Einsteiger finden...
Welche hilfreichen Stellen hast Du gefunden? Und hättest Du einen Vorschlag, wo man das anfängergerecht bündeln kann?
Um Objekte oder Arrays echt zu kopieren, muss man sich gut überlegen, was man haben will. Es gibt flache und tiefe Kopien.
Bei einer flachen Kopie werden die Eigenschaften aus a nach b übertragen. Falls die Eigenschaftswerte ihrerseits Objekte oder Arrays sind, wird nur der Verweis übertragen.
Bei einer tiefen Kopie wird beim Übertragen einer Eigenschaft, deren Wert ein Array oder Objekt ist, eine tiefe Kopie dieses Wertes erstellt. Das ist ein rekursiver Vorgang, der mit etwas Pech Zeit kostet und mit viel Pech das Script abschießt (wenn das zu klonende Objekt nämlich keine einfache Baumstruktur ist, sondern ein Graph mit Rückverweisen, dann gibt's eine Endlosrekursion bis der Aufrufstapel überläuft). Eine tiefe Kopie muss also gut überlegt werden, das macht man nur, wenn es wirklich nötig ist.
Der zweite Aspekt ist, ob man nur die aufzählbaren Eigenschaften übertragen möchte oder auch die nicht aufzählbaren Eigenschaften. Aufzählbarkeit ist etwas, das man pro Objekteigenschaft festlegen kann. Normalerweise sind Eigenschaften aufzählbar, einige aber nicht. Zum Beispiel die length-Eigenschaft eines Arrays, die ist nicht aufzählbar.
Und drittens fragt es sich, ob man nur Eigenschaften mit einem String als Schlüssel übertragen möchte, oder auch die, deren Schlüssel ein Symbol ist.
Eine einfache Methode, um eine flache Kopie eines Objekts zu erhalten (also eines assoziativen Arrays), bei der alle aufzählbaren Eigenschaften übertragen werden (egal ob der Schlüssel ein String oder ein Symbol ist), ist der Spread-Operator …. Den gibt's in jedem aktuellen Brauser. Im IE nicht, aber der interessiert keinen mehr.
const s = Symbol();
const a = { foo: 7, bar: 99, [s]: "symbolisch" };
const b = { ... a };
console.log("b.foo: ", b.foo);
console.log("b.bar: ", b.bar);
console.log("b.[s]: ", b.[s]);
Mit Arrays ging das schon, bevor es mit Objekten ging, da verwendest Du eckige Klammern beim Spread. Es gibt nur leichte Fehler bei schwach besetzten Arrays…
const arr1 = [ 4, 7, 9 ];
arr1[99] = 17;
const arr2 = [ ...arr1 ];
console.log(arr1.hasOwnProperty(5));
console.log(arr2.hasOwnProperty(5));
Im Ergebnis haben arr1 und arr2 beide die Länge 100, aber in arr1 sind die Indizes 3 bis 98 nicht existent, während sie in arr2 existieren und den Wert undefined haben. D.h. arr2 braucht mehr Speicher. Aber im Normalfall stört das keinen 😀
Rolf
--
sumpsi - posui - obstruxi