Der Array-Konstruktor ist eine eingebaute Funktion zur Array-Erzeugung — als Alternative zur Literalsyntax []. Er kann mit oder ohne new aufgerufen werden (new Array() und Array() sind äquivalent) und akzeptiert null, ein oder mehrere Argumente. Die berüchtigte Falle: bei genau einem numerischen Argument wird die Zahl als length interpretiert, nicht als Element — new Array(5) liefert ein sparse Array der Länge 5, nicht [5]. Seit ES2015 löst Array.of() dieses Inkonsistenz-Problem. In modernem Code ist das Literal [] der erste Wahl; der Konstruktor bleibt für dynamische Längen und Sparse-Array-Konstruktion relevant.

Drei Aufruf-Formen

Array() verhält sich je nach Anzahl der Argumente unterschiedlich.

JavaScript drei-formen.js
// 1. Ohne Argument: leeres Array
const a = new Array();
console.log(a, a.length);            // [] 0

// 2. Mit EINEM numerischen Argument: sparse Array dieser Länge
const b = new Array(3);
console.log(b, b.length);            // [ <3 empty items> ] 3
console.log(0 in b);                 // false — kein echtes Element

// 3. Mit MEHREREN Argumenten oder nicht-numerisch: Elemente direkt
const c = new Array(1, 2, 3);
console.log(c);                      // [1, 2, 3]
const d = new Array('hi');
console.log(d);                      // ['hi']
Output
[] 0
[ <3 empty items> ] 3
false
[ 1, 2, 3 ]
[ 'hi' ]

Diese Verzweigung beim einzigen numerischen Argument ist die Wurzel fast aller Konfusion rund um den Array-Konstruktor.

Sparse Arrays — Löcher statt Werte

Ein Array mit „leeren Plätzen" ist sparse — die length ist hochgesetzt, aber an den Positionen existiert kein eigener Property-Eintrag. Das hat subtile Konsequenzen.

JavaScript sparse.js
const sparse = new Array(3);

console.log(sparse.length);          // 3
console.log(sparse[0]);              // undefined
console.log(0 in sparse);            // false — Loch, kein Eintrag

// forEach überspringt Löcher!
sparse.forEach((v, i) => console.log('Index', i));
// → Keine Ausgabe — alle drei sind Löcher

// map auch — Löcher bleiben Löcher
const verdoppelt = sparse.map(x => x * 2);
console.log(verdoppelt);             // [ <3 empty items> ]

// for-of ITERIERT aber über sie (liefert undefined)
for (const x of sparse) console.log('Iter:', x);
Output
3
undefined
false
Iter: undefined
Iter: undefined
Iter: undefined

Das unterschiedliche Verhalten von forEach (überspringt Löcher) und for-of (iteriert sie) ist eine berüchtigte Falle. Daher: sparse Arrays nur bewusst und mit Plan einsetzen.

Array.of() — die saubere Alternative (ES2015)

Array.of() behandelt jedes Argument als Element, egal Anzahl oder Typ. Damit verschwindet die Konstruktor-Inkonsistenz.

JavaScript array-of.js
// Konstruktor — Falle bei einer Zahl
console.log(new Array(3));           // [ <3 empty items> ]

// Array.of — immer als Element
console.log(Array.of(3));            // [3]
console.log(Array.of(1, 2, 3));      // [1, 2, 3]
console.log(Array.of('hi'));         // ['hi']
console.log(Array.of());             // []
Output
[ <3 empty items> ]
[ 3 ]
[ 1, 2, 3 ]
[ 'hi' ]
[]

In Code, der eine variable Anzahl von Argumenten in ein Array packen soll, ist Array.of(...args) die korrekte Form. Pre-ES2015 musste man [].concat(args) oder ähnliche Tricks nutzen.

Vorbefüllen mit fill()

Ein sparse Array per Konstruktor + fill() ist das schnelle Pattern, ein Array bestimmter Länge mit demselben Wert vorzubereiten.

JavaScript fill.js
// Schnell: 10 Nullen
const nullen = new Array(10).fill(0);
console.log(nullen);

// 5 leere Arrays — Achtung: ALLE zeigen auf DASSELBE Array!
const matrix = new Array(3).fill([]);
matrix[0].push('A');
console.log(matrix);                 // alle drei haben 'A'!

// Korrekt: pro Position eigene Instanz mit Array.from + Mapper
const matrix2 = Array.from({ length: 3 }, () => []);
matrix2[0].push('A');
console.log(matrix2);                // nur erstes hat 'A'
Output
[
  0, 0, 0, 0, 0,
  0, 0, 0, 0, 0
]
[ [ 'A' ], [ 'A' ], [ 'A' ] ]
[ [ 'A' ], [], [] ]

Die fill-Falle: bei Objekten/Arrays als Füllwert wird die gleiche Referenz an jede Position gesetzt. Wer pro Position eine eigene Instanz braucht, muss Array.from({ length: n }, () => factory()) nutzen.

Mit new oder ohne — egal

Anders als bei klassischen Konstruktoren spielt new bei Array() keine Rolle.

JavaScript mit-ohne-new.js
const a = new Array(1, 2, 3);
const b = Array(1, 2, 3);

console.log(a);                      // [1, 2, 3]
console.log(b);                      // [1, 2, 3]
console.log(a.constructor === b.constructor); // true
Output
[ 1, 2, 3 ]
[ 1, 2, 3 ]
true

Die Sprache definiert Array so, dass der Aufruf intern dasselbe macht, ob new davor steht oder nicht. Style-Guides empfehlen meist die kürzere Array(...)-Form.

Maximal-Länge

Die Spec erlaubt Arrays bis 2^32 - 1 Elemente (≈ 4,29 Milliarden). Negative oder nicht-ganzzahlige Zahlen werfen RangeError.

JavaScript max-laenge.js
const max = 2 ** 32 - 1;
console.log('Max length:', max);

try {
    new Array(-1);
} catch (e) {
    console.log('Negativ:', e.message);
}

try {
    new Array(1.5);
} catch (e) {
    console.log('Float:', e.message);
}

try {
    new Array(2 ** 32);
} catch (e) {
    console.log('Zu groß:', e.message);
}
Output
Max length: 4294967295
Negativ: Invalid array length
Float: Invalid array length
Zu groß: Invalid array length

In der Praxis sind Arrays mit Millionen Elementen schon problematisch wegen Speicher und GC — der theoretische Maximalwert ist selten relevant.

Typed Array-Konstruktoren — andere Mechanik

Typed Arrays (Int8Array, Float32Array, etc.) haben eigene Konstruktoren mit eigener Semantik — kein direkter Bezug zum klassischen Array-Konstruktor.

JavaScript typed-array.js
// Mit Länge: direkt mit Nullen initialisiert (kein sparse-Verhalten)
const ints = new Int32Array(3);
console.log(ints);                   // Int32Array(3) [0, 0, 0]
console.log(0 in ints);              // true — echte Werte

// Mit Array
const floats = new Float32Array([1.5, 2.5, 3.5]);
console.log(floats);

// Mit ArrayBuffer
const buf = new ArrayBuffer(8);      // 8 Bytes
const view = new Uint8Array(buf);
view[0] = 255;
console.log(view);
Output
Int32Array(3) [ 0, 0, 0 ]
true
Float32Array(3) [ 1.5, 2.5, 3.5 ]
Uint8Array(8) [
  255, 0, 0, 0,
    0, 0, 0, 0
]

Typed Arrays haben kein sparse-Verhalten — jedes Element ist initialisiert (mit dem Typ-spezifischen Null-Wert). Detail-Behandlung in einem eigenen Artikel.

Wann welche Form?

SituationEmpfehlung
Bekannte Elemente, statischLiteral: [1, 2, 3]
Variable Argument-ListeArray.of(...args)
Sparse Array für .fill(wert)new Array(n).fill(wert)
Pro Position eigene InstanzArray.from({length: n}, factory)
Iterable in Array konvertierenArray.from(iterable) oder [...iterable]
Typed Array (Performance, Binärdaten)new Int32Array(...) etc.

Häufige Stolperfallen

new Array(3) ist NICHT [3]

Klassische Anfänger-Falle. new Array(3) liefert ein leeres sparse Array der Länge 3 — kein Array mit dem Wert 3 drin. Wer ein Single-Element-Array will: Array.of(3) oder [3].

fill() mit Object teilt Referenzen

new Array(3).fill([]) erzeugt drei Positionen, die ALLE auf dasselbe Array zeigen. Mutation an einem mutiert „alle". Lösung: Array.from({length: 3}, () => []) — der Mapper produziert pro Position eine neue Instanz.

forEach überspringt Löcher, for-of nicht

Sparse Arrays sind die Quelle subtiler Bugs. arr.forEach, arr.map, arr.filter überspringen Löcher — der Callback wird für sie nicht aufgerufen. for...of dagegen iteriert sie und liefert undefined. arr.length zählt sie mit.

Array.of seit ES2015 — die saubere Lösung

Array.of(...args) behandelt jedes Argument als Element, unabhängig von Anzahl oder Typ. Kein Sonder-Verhalten bei einer Zahl. In Code, der variable Argumente in ein Array packt, ist das die idiomatische Form.

new ist optional — Array() und new Array() identisch

Spec-Eigenschaft: der Konstruktor verhält sich mit und ohne new gleich. Style-Guides empfehlen meist die kürzere Form ohne new. Andere Konstruktoren wie Date oder Map haben dieses Verhalten NICHT — da ist new Pflicht.

Negative oder nicht-ganzzahlige Länge wirft RangeError

new Array(-1), new Array(1.5), new Array(NaN) alle: RangeError: Invalid array length. Wer dynamisch eine Länge berechnet, muss sicherstellen, dass das Resultat eine nicht-negative Ganzzahl im erlaubten Bereich ist.

Bei Realm-Übergang (iframes) hat jedes Realm seinen eigenen Array

Ein Array aus einem iframe ist NICHT instanceof Array im Parent-Realm — die Array-Konstruktoren sind getrennt. Robust: Array.isArray(x) nutzen, das funktioniert Realm-übergreifend.

Spread auf den Konstruktor: Array(...iter) hat keine sparse-Falle

Array(...iter) spreaded das Iterable in Argumente — mehrere Argumente, also kein Sonder-Verhalten. Praktisch äquivalent zu [...iter] oder Array.from(iter). Selten gesehen, weil die Alternativen lesbarer sind.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Arrays

Zur Übersicht