Skip to content

Türchen 22

Published: at 07:00 AMSuggest Changes

Erweiterte Methoden zur Array-Manipulation in ES2023

Welche neue Methoden sind das?

Mit ES2023 (ECMAScript 2023) wurde JavaScript um vier neue Array-Methoden erweitert, die die bestehende Funktionalität maßgeblich ergänzen:

  1. toReversed()
  2. toSorted()
  3. toSpliced()
  4. with()

Sie alle haben eines gemeinsam: Sie mutieren das Array nicht, sondern geben eine neue Kopie mit den entsprechenden Veränderungen zurück. Dieser nicht-destruktive Ansatz hat sich in der Praxis vielfach bewährt, z. B. in funktionalen oder reaktiven Programmiermustern, wo das Immutability-Prinzip eine große Rolle spielt. In diesem Blogpost schauen wir uns an, wie sie sich von den bereits existierenden Methoden unterscheiden und wie sie im Alltag eingesetzt werden können.

Warum neue Methoden?

Bisher gab es in JavaScript bereits Methoden wie reverse(), sort() oder splice(). Leider haben diese Methoden jedoch einen entscheidenden Nachteil, sie mutieren das Array direkt. Will man eine unveränderte Kopie behalten – zum Beispiel um in einer State-Management-Lösung das Original zu wahren – musste man eigene Workarounds anwenden, wie etwa das Array vorher zu klonen:

const original = [3, 1, 2];
const copy = [...original];  // Kopie via Spread
copy.sort((a, b) => a - b);
// copy -> [1, 2, 3], original -> [3, 1, 2]

Mit den neuen Methoden toReversed(), toSorted(), toSpliced() und with() löst JavaScript dieses Problem von sich aus. Jede dieser Methoden erzeugt eine neue Version des Arrays und lässt das Ausgangsarray unverändert. Das macht den Code lesbarer, Fehlerquellen werden reduziert, und es folgt den Prinzipien einer immutablen Datenverarbeitung.

Lass wir uns jetzt den einzelnen neuen Methoden zuwenden und sie näher anschauen.

1. toReversed()

Was macht es?

Ähnlich wie reverse() sortiert toReversed() ein vorhandenes Array in umgekehrter Reihenfolge. Dabei zerstört es jedoch das ursprüngliche Array nicht, sondern legt ein neues Array an. Wie bereits beschrieben erzeugt es eine Kopie des Arrays in umgekehrter Reihenfolge.

Beispiel:

const original = [1, 2, 3];

// Bisher:
const reversedOldWay = [...original].reverse();
console.log(reversedOldWay); // [3, 2, 1]
console.log(original);       // [1, 2, 3]

// Neu mit toReversed():
const reversedNewWay = original.toReversed();
console.log(reversedNewWay); // [3, 2, 1]
console.log(original);       // [1, 2, 3] (unverändert)

Wozu ist das nützlich?
Wenn du nur kurz die Reihenfolge eines Arrays umkehren möchtest, um das Ergebnis woanders zu verwenden, musst du nicht mehr darauf achten, das Original zu kopieren oder unabsichtlich zu verändern. In vielen State-Management-Szenarien ist das ein großer Vorteil.

2. toSorted(compareFn)

Was macht es?

Wie das bekannte sort() gibt Dir toSorted() eine nach Deinen Wünschen sortiertes Array zurück. Der Vorteil liegt auch hier darin, dass es Dein Ursprungsarray nicht verändert, sondern eine Kopie dessen anlegt. Dieses ursprüngliche Array steht Dir also weiterhin zur Verfügung.

Beispiel:

const numbers = [4, 2, 7, 1];

// Bisher:
const sortedOldWay = [...numbers].sort((a, b) => a - b);
console.log(sortedOldWay); // [1, 2, 4, 7]
console.log(numbers);      // [4, 2, 7, 1] (unverändert)

// Neu:
const sortedNewWay = numbers.toSorted((a, b) => a - b);
console.log(sortedNewWay); // [1, 2, 4, 7]
console.log(numbers);      // [4, 2, 7, 1] (unverändert)

Wozu ist das nützlich?
Für jeden Anwendungsfall, bei dem das Sortieren eines Arrays benötigt wird, ohne das Original zu verändern. Ein praktisches Beispiel wäre eine Such- oder Filterkomponente, bei der man eine sortierte Darstellung anbietet, aber die Datenquelle unangerührt lassen will.

3. toSpliced(start, deleteCount, ...items)

Was macht es?

So wie splice() werden auch in toSpliced() an an einer bestimmten Stelle Elemente entfernt und/oder neue Elemente eingefügt. Auch hier ist der Unterschied, dass die Rückgabe in einem neuen Array erfolgt, so mit also immutabel ist.

Der Syntax ist die folgende:

toSpliced(start, deleteCount, ...items)

Beispiel:

// Bisher (destruktiv)
const org1 = [10, 20, 30, 40];
const new1 = org1.splice(1, 2, 99);
console.log(new1); // [20, 30]          (gelöschte Werte)
console.log(org1); // [10, 99, 40]      (verändert)

// Neu (nicht-destruktiv)
const org2 = [10, 20, 30, 40];
const new2 = org2.toSpliced(1, 2, 99);
console.log(new2); // [10, 99, 40]      (verändert)
console.log(org2); // [10, 20, 30, 40]  (unverändert)

// Kombination mit Workaround (nicht-destruktiv)
const org3 = [10, 20, 30, 40];
const cop3 = [...org3];
const rem3 = cop3.splice(1, 2, 99);
const new3 = org3.toSpliced(1, 2, 99);
console.log(rem3); // [20, 30]          (gelöschte Werte)
console.log(new3); // [10, 99, 40]      (verändert)
console.log(org3); // [10, 20, 30, 40]  (unverändert)

Was passiert hier genau?

In diesem Codebeispiel vergleichen wir die Array-Methoden splice() und toSpliced().

Zunächst wird ein Array org1 mit den Werten [10, 20, 30, 40] erstellt. Die Methode splice() wird verwendet, um zwei Elemente ab Index 1 zu entfernen und durch den Wert 99 zu ersetzen. Das Ergebnis der splice-Operation, das die entfernten Werte [20, 30] enthält, wird in new1 gespeichert. Das ursprüngliche Array org1 wird durch die splice-Operation verändert und enthält nun [10, 99, 40].

Im nächsten Abschnitt wird ein weiteres Array org2 mit denselben Werten erstellt. Dann wird die Methode toSpliced() verwendet, um die Änderung durchzuführen. Das neue Array, dass diese Operation erstellt, sieht jetzt aus wie erwartet [10, 99, 40]. Da die Methode toSpliced() jedoch eine Kopie des original Arrays anlegt, bleibt die ursprüngliche Array org2 hier unverändert und enthält weiterhin [10, 20, 30, 40].

Wenn ich auf den Array mit den gelöschten Werten nicht verzichten kann, wird die Sache leider noch ein wenig komplexer. Hier muss ich zuerst eine Kopie des Originals erzeugen, auf dass ich dann mit splice() einen neuen Array mit den gelöschten Werten erhalte. Auf das Original wende ich dann toSpliced() an und erhalte einen neuen Array mit den veränderten Werten zurück. Das Original bleibt hier dann wie erwartet unverändert.

Wozu ist das nützlich?
Wenn du z. B. in einem UI nachträglich Elemente einfügen oder entfernen musst, ohne das Originalarray direkt zu verändern. Klassisches Beispiel: eine Liste von Items (z. B. Artikel in einem Warenkorb), die man kopiert, um neue Einträge hinzuzufügen oder zu entfernen, ohne das gesamte Modell zu überschreiben.

4. with(index, value)

Was macht es?

Die neue Array-Methode with() erzeugt eine Kopie des Arrays, bei der das Element am Index index auf value gesetzt wurde. Auch diese neue Methode ist immutabel. Das Original bleibt auch hier natürlich wieder unverändert.

Beispiel:

// Bisher (destruktiv)
const arr1 = [5, 10, 15];
arr1[1] = 99;
console.log(arr1);  // [5, 99, 15] (verändert)

// Neu (nicht-destruktiv)
const arr2 = [5, 10, 15];
const mod2 = arr2.with(1, 99);
console.log(mod2);  // [5, 99, 15] (verändert)
console.log(arr2);  // [5, 10, 15] (unverändert)

Wozu ist das nützlich?
Wenn du nur ein einziges Element ändern möchtest, aber das Original nicht anrühren willst. Denk an reaktive Frontends, in denen jeder State-Änderung eine Kopie des alten States entspricht.


Fazit

Mit toReversed(), toSorted(), toSpliced() und with() zieht JavaScript in Bezug auf nicht-destruktive Array-Operationen nach. Bisher war es Standard, manuelle Kopien zu erstellen oder auf Bibliotheken/Funktionen zurückzugreifen, um Immutability zu gewährleisten. Diese neue Ergänzung in ES2023 vereinfacht den Code, macht Intentionalität klarer und verhindert nebenbei viele Fehler, die aus versehentlicher Array-Mutation resultieren könnten.

Vorteile im Überblick

Mit diesem Schritt legt JavaScript einen weiteren Fokus auf funktionale Programmiermuster und robuste Datenverarbeitung. Wer immutabel arbeiten möchte, kann das zukünftig noch bequemer direkt mit den Bordmitteln von ES2023 tun.

Experimentiere mit den neuen Array Methoden und entdecke sie, um in Zukunft einfacher von den Vorteilen von Immutability zu profitieren!


Previous Post
Türchen 23
Next Post
Türchen 21