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

JavaScript signatur.js
arr.unshift(...werte: T[]): number   // neue Länge nach unshift
JavaScript grundform.js
const 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]
Output
[ 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.

JavaScript performance.js
// 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]
Output
[ 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:

JavaScript immutable.js
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]
Output
[ 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.

JavaScript reihenfolge.js
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
Output
[ '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:

JavaScript spread-arg.js
const arr = [5, 6];
const front = [1, 2, 3, 4];

arr.unshift(...front);
console.log(arr);            // [1, 2, 3, 4, 5, 6]
Output
[ 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:

JavaScript queue-vergleich.js
// 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-Datenstruktur
Output
A
A

Beide Varianten haben O(n)-Operationen — bei riesigen Queues lohnt sich eine echte Deque/Linked-List.

unshift auf Array-Like

JavaScript arraylike.js
const arrayLike = { 0: 'b', 1: 'c', length: 2 };

Array.prototype.unshift.call(arrayLike, 'a');
console.log(arrayLike);
Output
{ '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.

JavaScript tospliced.js
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]
Output
[ 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

/ Weiter

Zurück zu Arrays

Zur Übersicht