toSorted, toReversed und with: Arrays sortieren, ohne das Original zu zerstören
array.sort() sortiert nicht eine Kopie, sondern das Array selbst – und genau daran ist schon mancher Zustand im Frontend stillschweigend kaputtgegangen. Seit ES2023 gibt es zu jeder dieser Methoden eine Variante, die eine Kopie zurückgibt.
Der Fehler sieht harmlos aus:
function teuersteZuerst(produkte) {
return produkte.sort((a, b) => b.preis - a.preis);
}Die Funktion gibt zwar eine sortierte Liste zurück – aber sie sortiert dabei die übergebene Liste selbst um. Wer danach produkte in der ursprünglichen Reihenfolge braucht, bekommt sie nicht mehr. In einem Framework, das seinen Zustand mit dem vorherigen vergleicht, ist der Effekt noch unangenehmer: Vorher und Nachher sind dasselbe Objekt, also „hat sich nichts geändert", und die Oberfläche zeichnet nicht neu.
Seit ES2023 gibt es zu den vier verändernden Array-Methoden je eine, die stattdessen eine Kopie liefert.
Die vier neuen Methoden
const preise = [30, 5, 12];
preise.toSorted((a, b) => a - b); // [5, 12, 30] – neues Array
preise.toReversed(); // [12, 5, 30] – neues Array
preise.with(1, 99); // [30, 99, 12] – ein Feld ersetzt
preise.toSpliced(1, 1); // [30, 12] – ein Feld entfernt
console.log(preise); // [30, 5, 12] ← unverändert| verändert das Original | gibt eine Kopie zurück | |---|---| | sort() | toSorted() | | reverse() | toReversed() | | arr[i] = x | with(i, x) | | splice() | toSpliced() |
Die Funktion von oben wird damit zu einer, die hält, was ihr Name verspricht:
const teuersteZuerst = (produkte) => produkte.toSorted((a, b) => b.preis - a.preis);Drei Dinge, die dich sonst erwischen
toSorted() ohne Vergleichsfunktion sortiert wie Text. Genau wie sort(). [30, 5, 12] wird zu [12, 30, 5], weil "12" vor "30" vor "5" kommt. Bei Zahlen gehört die Vergleichsfunktion also weiterhin dazu – die neue Methode ändert daran nichts.
Die Kopie ist flach. Das neue Array ist neu, die Objekte darin sind dieselben. Änderst du kopie[0].name, ändert sich auch original[0].name. Willst du wirklich alles lösen, brauchst du structuredClone.
with() wirft bei einem Index außerhalb der Liste. [1, 2].with(5, 0) ergibt einen RangeError und nicht etwa stillschweigend ein Loch – das ist gut so, macht aber aus einer Zuweisung eine Stelle, an der man auf den Index achten muss. Negative Indizes zählen wie überall von hinten: .with(-1, 0) ersetzt das letzte Feld.
Wo ich das benutze
Überall dort, wo eine Liste angezeigt wird und die Sortierung nur die Ansicht betrifft: eine Tabelle, die man nach Spalten sortieren kann, eine Bestenliste, ein Stapel Karten. Der Zustand bleibt, wie er ist, und die Anzeige bekommt ihre eigene Reihenfolge. Das spart genau die Sorte Fehler, die man erst drei Klicks später bemerkt – und dann lange sucht.
Unterstützt wird das von allen aktuellen Browsern und ab Node 20. Wenn du noch ältere Umgebungen bedienen musst, tut es [...arr].sort(...) genauso; die neuen Methoden sagen nur deutlicher, was gemeint ist.
Mehr solcher Kleinigkeiten, die im Alltag Zeit sparen, sammle ich laufend auf code.bymw.de – schau gern regelmäßig vorbei.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Set und Map in JavaScript – doppelte Einträge loswerden und richtig zählen
Ein Objekt als Nachschlagetabelle geht – bis der Schlüssel eine Zahl ist, oder ein Objekt, oder zufällig "constructor" heißt. Set und Map machen genau das, wofür man Objekte bisher zweckentfremdet hat, nur ohne die Überraschungen.
Aufzählungen richtig verketten mit Intl.ListFormat
"a, b und c" von Hand zusammenzubauen geht fast immer schief – bei einem Element, bei zwei Elementen, beim letzten Komma. Intl.ListFormat macht es richtig, in jeder Sprache, ganz ohne Bibliothek.
requestAnimationFrame – die Animationsschleife, die zum Bildschirm passt
setInterval(schritt, 16) läuft auf einem 144-Hz-Monitor anders als auf einem alten Handy – und im Hintergrundtab einfach weiter. requestAnimationFrame löst beides, wenn man die verstrichene Zeit mitrechnet statt Bilder zu zählen.