Array.prototype.unshift() ist das Spiegelbild zu push: ein oder mehrere Elemente werden am Anfang des Arrays eingefügt, alle existierenden rücken um die Anzahl der neuen Elemente nach hinten. Wie push mutiert die Methode das Original und liefert die neue Länge zurück. Anders als push ist unshift aber O(n) — jedes vorhandene Element bekommt einen neuen Index. Bei großen Arrays ist das spürbar; das Pre-Pend-Pattern [neu, ...arr] mit Spread ist oft die bessere Wahl, weil es zumindest klar ein neues Array erzeugt und nicht in-place rekursive Index-Shifts auslöst.
Signatur & Grundform
arr.unshift(...werte: T[]): number // neue Länge nach unshiftconst arr = [2, 3, 4];
const neueLaenge = arr.unshift(1);
console.log(arr); // [1, 2, 3, 4]
console.log(neueLaenge); // 4 — Länge, nicht das Array
// Mehrere Elemente — Reihenfolge bleibt erhalten
arr.unshift(-1, 0);
console.log(arr); // [-1, 0, 1, 2, 3, 4][ 1, 2, 3, 4 ]
4
[ -1, 0, 1, 2, 3, 4 ]Wichtig: bei mehreren Argumenten landen sie in derselben Reihenfolge wie übergeben. Also unshift(a, b, c) führt zu [a, b, c, ...rest], nicht [c, b, a, ...rest].
Performance — O(n) wegen Reindexing
Jedes bestehende Element bekommt einen neuen Index. Bei einem Array der Länge n ist unshift daher O(n) — anders als push, das O(1) ist.
// Bei N unshifts in eine Schleife: O(N²) gesamt
const N = 5;
const arr = [];
for (let i = 0; i < N; i++) {
arr.unshift(i);
}
console.log(arr); // [4, 3, 2, 1, 0]
// Bei sehr großen Arrays — pop + reverse ist schneller
const items = [];
for (let i = 0; i < N; i++) items.push(i);
items.reverse();
console.log(items); // [4, 3, 2, 1, 0][ 4, 3, 2, 1, 0 ]
[ 4, 3, 2, 1, 0 ]Bei normalem Anwendungs-Code unmessbar. Bei Hot-Loops mit großen Arrays kann es zum Bottleneck werden.
Immutable: Spread-Pre-Pend
In React/Redux: niemals unshift. Stattdessen ein neues Array mit Spread:
const original = [2, 3];
const vornNeu = [1, ...original];
console.log(original); // [2, 3] — unverändert
console.log(vornNeu); // [1, 2, 3]
// Mehrere vorn
const mehr = [-1, 0, ...original];
console.log(mehr); // [-1, 0, 2, 3]
// toSpliced (ES2023) — generisch
const eingefuegt = original.toSpliced(0, 0, 1);
console.log(eingefuegt); // [1, 2, 3][ 2, 3 ]
[ 1, 2, 3 ]
[ -1, 0, 2, 3 ]
[ 1, 2, 3 ]Mehrere Argumente — Reihenfolge erhalten
Eine häufig übersehene Eigenschaft: bei mehreren Argumenten landen sie als Block am Anfang, in der übergebenen Reihenfolge.
const arr = ['c'];
arr.unshift('a', 'b');
console.log(arr); // ['a', 'b', 'c'] — NICHT ['b', 'a', 'c']
// Im Vergleich: nacheinander einzeln
const arr2 = ['c'];
arr2.unshift('a');
arr2.unshift('b');
console.log(arr2); // ['b', 'a', 'c'] — jeder unshift schiebt vorne rein[ 'a', 'b', 'c' ]
[ 'b', 'a', 'c' ]Daher: lieber unshift(a, b, c) einmal als drei mal unshift — sowohl Performance als auch Reihenfolge sind dann eindeutig.
unshift mit Spread eines Arrays
Wer ein ganzes Array vorn anhängen will, nutzt Spread im Argument:
const arr = [5, 6];
const front = [1, 2, 3, 4];
arr.unshift(...front);
console.log(arr); // [1, 2, 3, 4, 5, 6][ 1, 2, 3, 4, 5, 6 ]In der Praxis ist arr = [...front, ...arr] oft lesbarer — und immutable.
unshift + pop als Queue — möglich, aber schlecht
Manche Tutorials zeigen unshift zusammen mit pop als Queue-Pattern (FIFO). Funktioniert, ist aber schlechter als push + shift:
// Schlecht: unshift + pop — unshift ist O(n)
const q1 = [];
q1.unshift('A'); // O(1) bei leerem Array
q1.unshift('B'); // O(2)
q1.unshift('C'); // O(3)
console.log(q1.pop()); // 'A' — FIFO
// Üblich: push + shift — shift ist O(n), aber push ist O(1)
const q2 = [];
q2.push('A'); q2.push('B'); q2.push('C');
console.log(q2.shift()); // 'A' — FIFO
// Beste FIFO-Form bei vielen Elementen: dedizierte Queue-DatenstrukturA
ABeide Varianten haben O(n)-Operationen — bei riesigen Queues lohnt sich eine echte Deque/Linked-List.
unshift auf Array-Like
const arrayLike = { 0: 'b', 1: 'c', length: 2 };
Array.prototype.unshift.call(arrayLike, 'a');
console.log(arrayLike);{ '0': 'a', '1': 'b', '2': 'c', length: 3 }toSpliced(0, 0, ...werte) — immutable Pre-Pend
ES2023 bietet mit toSpliced eine generische immutable Splice-Methode. Mit start=0, deleteCount=0 ist sie das immutable Pendant zu unshift.
const original = [3, 4, 5];
const vorne = original.toSpliced(0, 0, 1, 2);
console.log(original); // [3, 4, 5] — unverändert
console.log(vorne); // [1, 2, 3, 4, 5][ 3, 4, 5 ]
[ 1, 2, 3, 4, 5 ]Interessantes
unshift ist O(n) — nicht O(1) wie push
Jedes vorhandene Element bekommt einen neuen Index. Bei N Elementen also N Schreib-Operationen. Im Hot-Loop kann das den Unterschied machen — push + reverse am Ende ist oft schneller, wenn die Reihenfolge umkehrbar ist.
Rückgabewert ist neue Länge, nicht das Array
Wie push gibt unshift die neue Länge zurück. const n = arr.unshift(x) setzt n auf eine Zahl. Chain-Aufrufe (arr.unshift(x).map(...)) funktionieren NICHT — die Zahl hat keine map-Methode.
Mehrere Argumente: Reihenfolge wie übergeben, als Block vorn
arr.unshift(a, b, c) ergibt [a, b, c, ...rest]. Klingt offensichtlich, ist aber leicht zu vergessen — manche Anfänger erwarten [c, b, a, ...rest], weil sie an „dreimal nacheinander unshift" denken.
In React/Redux: niemals unshift
Mutation, falscher Rückgabewert. Korrekt: [neu, ...state] oder state.toSpliced(0, 0, neu) (ES2023). Beide erzeugen neue Referenz, React rendert neu.
Spread-Pre-Pend ist äquivalent, aber neues Array
arr = [neu, ...arr] ist semantisch identisch mit arr.unshift(neu), erzeugt aber ein neues Array. In Performance-Loops mit vielen Operationen am Anfang ist eine echte Deque-Datenstruktur die richtige Wahl.
unshift erzeugt nie Löcher
Jedes übergebene Argument landet als echtes Element. Sparse-Slots im Quell-Array werden allerdings übernommen — wer ein sparse Array unshiftet, behält die Löcher.
Queue: push + shift, NICHT unshift + pop
Beide Varianten haben eine O(n)-Operation. push + shift ist konventioneller — Code-Leser erwarten das. Für massive Queues: dedizierter Datentyp.
toSpliced(0, 0, x) als immutable Variante seit ES2023
Baseline 2024 — in modernen Codebases verfügbar. Vorher: [x, ...arr]. Beide funktional identisch, toSpliced ist nur eine andere API-Form für dieselbe Operation.
Weiterführende Ressourcen
Externe Quellen
- Array.prototype.unshift() – MDN
- Array.prototype.toSpliced() – MDN
- Array.prototype.unshift – ECMAScript Spec