Array.from() ist die universale Brücke von iterierbaren und array-like Objekten zu echten Arrays. Sie nimmt eine Quelle plus optional einen Mapper-Callback und liefert ein neues Array. Iterables sind alle Strukturen mit Symbol.iterator (String, Set, Map, NodeList, Generator). Array-likes sind Objekte mit length-Property und nummerischen Keys (arguments, manche DOM-Collections). Mit dem { length: n }-Trick lässt sich auch ein synthetisches Array fester Länge erzeugen — sehr praktisch zur Initialisierung. Seit ES2024 gibt es Array.fromAsync() für AsyncIterables.

Signatur

JavaScript signatur.js
Array.from(source, mapFn?, thisArg?): Array
  • source: ein Iterable oder Array-Like
  • mapFn: optionaler Callback (element, index) => neu
  • thisArg: optional, this-Wert für den Mapper
JavaScript grundform.js
// Iterable: Set → Array
console.log(Array.from(new Set([1, 2, 2, 3])));   // [1, 2, 3]

// Iterable: String → Array von Codepoints
console.log(Array.from('abc'));                   // ['a', 'b', 'c']

// Array-like: arguments → Array
function f() { return Array.from(arguments); }
console.log(f(10, 20, 30));                       // [10, 20, 30]

// Mit Mapper
console.log(Array.from([1, 2, 3], x => x * 10));  // [10, 20, 30]
Output
[ 1, 2, 3 ]
[ 'a', 'b', 'c' ]
[ 10, 20, 30 ]
[ 10, 20, 30 ]

Iterable vs. Array-Like

Zwei verschiedene Protokolle — beide funktionieren mit Array.from().

JavaScript iterable-vs-arraylike.js
// ITERABLE: hat Symbol.iterator
const iterable = {
    *[Symbol.iterator]() {
        yield 'a';
        yield 'b';
        yield 'c';
    },
};
console.log(Array.from(iterable));    // ['a', 'b', 'c']

// ARRAY-LIKE: hat length + numerische Keys
const arrayLike = { 0: 'x', 1: 'y', 2: 'z', length: 3 };
console.log(Array.from(arrayLike));   // ['x', 'y', 'z']

// arguments ist beides — Array-Like UND iterable
function f() {
    console.log(Array.from(arguments));
}
f(1, 2, 3);
Output
[ 'a', 'b', 'c' ]
[ 'x', 'y', 'z' ]
[ 1, 2, 3 ]

Array.from prüft zuerst auf Symbol.iterator — wenn vorhanden, nutzt es das Iterator-Protokoll. Sonst fällt es auf length + Index-Zugriff zurück.

Der { length: n }-Trick

Ein Objekt mit nur einer length-Property ist ein gültiges Array-Like. Array.from durchläuft Index 0 bis n-1 und liest dort — die Properties existieren nicht, also undefined.

JavaScript length-trick.js
// Array fester Länge mit undefined (kein sparse!)
const undefArr = Array.from({ length: 3 });
console.log(undefArr);                // [undefined, undefined, undefined]
console.log(0 in undefArr);           // true — echtes Element, kein Loch!

// Mit Mapper: 1..5
const zahlen = Array.from({ length: 5 }, (_, i) => i + 1);
console.log(zahlen);                  // [1, 2, 3, 4, 5]

// Pro Position eine neue Objekt-Instanz
const matrix = Array.from({ length: 3 }, () => []);
matrix[0].push('A');
console.log(matrix);                  // [['A'], [], []]
Output
[ undefined, undefined, undefined ]
true
[ 1, 2, 3, 4, 5 ]
[ [ 'A' ], [], [] ]

Dieses Pattern ist die idiomatische Form, ein Array bestimmter Länge mit dynamisch berechneten Werten zu initialisieren — und vermeidet die Sparse-Falle von new Array(n).

Mapper inline vs. .map() nachträglich

Array.from(src, mapFn) ist semantisch nahe an Array.from(src).map(mapFn), aber effizienter — in einem Schritt statt zwei Arrays nacheinander.

JavaScript mapper-vergleich.js
const set = new Set([1, 2, 3]);

// Zwei Arrays werden allokiert
const a = Array.from(set).map(x => x * 2);

// Ein Array — kombinierte Iteration
const b = Array.from(set, x => x * 2);

console.log(a);   // [2, 4, 6]
console.log(b);   // [2, 4, 6]
Output
[ 2, 4, 6 ]
[ 2, 4, 6 ]

Bei sehr großen Quellen lohnt die Inline-Form. Bei kleinen Datenmengen ist die .map()-Form oft lesbarer, weil die zwei Schritte klarer getrennt sind.

Array.from() vs. Spread [...iter]

Beide erzeugen ein Array aus einem Iterable. Unterschiede:

JavaScript from-vs-spread.js
const set = new Set([1, 2, 3]);

// Beide identisch bei Iterables
console.log(Array.from(set));      // [1, 2, 3]
console.log([...set]);             // [1, 2, 3]

// Aber: Array-Likes funktionieren NUR mit Array.from
const al = { 0: 'a', 1: 'b', length: 2 };
console.log(Array.from(al));       // ['a', 'b']
try {
    console.log([...al]);          // TypeError: al is not iterable
} catch (e) {
    console.log('Spread:', e.message);
}

// Array.from akzeptiert einen Mapper, Spread nicht
console.log(Array.from(set, x => x * 10));  // [10, 20, 30]
Output
[ 1, 2, 3 ]
[ 1, 2, 3 ]
[ 'a', 'b' ]
Spread: al is not iterable
[ 10, 20, 30 ]

Faustregel: bei Iterables ist Spread kürzer ([...iter]). Bei Array-Likes oder mit Mapper braucht's Array.from.

DOM-Beispiel — NodeList in echtes Array

Die häufigste Real-World-Anwendung im Browser: eine NodeList (z.B. von querySelectorAll) in ein echtes Array konvertieren, damit map/filter/reduce darauf funktionieren.

JavaScript dom-nodelist.js
// Direkt: liefert NodeList, kein echtes Array
const buttons = document.querySelectorAll('button');

// In Array konvertieren — Mapper inline
const buttonTexte = Array.from(buttons, b => b.textContent);

// Filter funktioniert dann
const aktive = Array.from(buttons).filter(b => !b.disabled);

// Spread funktioniert auch — NodeList ist seit modernen Browsern iterable
const alt = [...buttons];

NodeList ist seit ES2015 iterable — Spread und for-of funktionieren. HTMLCollection (von getElementsByTagName) ist nicht iterable — da hilft nur Array.from.

Bereiche und Sequenzen erzeugen

Mit dem length-Trick und einem Mapper lassen sich beliebige numerische Sequenzen in einer Zeile bauen.

JavaScript bereiche.js
// Zahlen 1..10
const r1 = Array.from({ length: 10 }, (_, i) => i + 1);
console.log(r1);

// Zahlen 0, 2, 4, ..., 18
const r2 = Array.from({ length: 10 }, (_, i) => i * 2);
console.log(r2);

// Quadrate
const r3 = Array.from({ length: 5 }, (_, i) => i * i);
console.log(r3);

// Zufalls-Floats
const r4 = Array.from({ length: 5 }, () => Math.random().toFixed(2));
console.log(r4);
Output
[
   1, 2, 3, 4,  5,
   6, 7, 8, 9, 10
]
[
   0,  2,  4,  6,  8,
  10, 12, 14, 16, 18
]
[ 0, 1, 4, 9, 16 ]
[ '0.18', '0.71', '0.42', '0.96', '0.23' ]

Pre-ES2015 hätte man dafür eine for-Schleife geschrieben. Mit Array.from reicht eine Zeile.

Array.fromAsync() — asynchrone Variante (ES2024)

Seit ES2024 gibt es das asynchrone Pendant für AsyncIterables (Streams, async Generators).

JavaScript from-async.js
async function* asyncRange(n) {
    for (let i = 0; i < n; i++) {
        await new Promise(r => setTimeout(r, 5));
        yield i;
    }
}

(async () => {
    const arr = await Array.fromAsync(asyncRange(5));
    console.log(arr);   // [0, 1, 2, 3, 4]

    // Mit Mapper
    const arr2 = await Array.fromAsync(asyncRange(3), x => x * 100);
    console.log(arr2);  // [0, 100, 200]
})();
Output
[ 0, 1, 2, 3, 4 ]
[ 0, 100, 200 ]

Browser-Support: Chrome 121+, Firefox 115+, Safari 16.4+, Node 22+ — Baseline 2024. Davor: manueller Loop mit for-await-of.

Interessantes

Iterables und Array-Likes — zwei Protokolle, eine Methode

Array.from testet zuerst auf Symbol.iterator (Iterable-Protokoll). Fehlt das, fällt es auf length + Index-Zugriff zurück (Array-Like-Protokoll). Spread [...x] kennt nur das Iterable-Protokoll, daher die Lücke bei reinen Array-Likes.

length-Trick erzeugt undefined-gefülltes Array, kein sparse

Array.from({length: 3}) liefert [undefined, undefined, undefined] — echte Elemente, kein Loch. new Array(3) liefert [<3 empty items>] — sparse mit Löchern. Wer mit map/filter darauf operieren will, muss Array.from nutzen.

Inline-Mapper ist effizienter als .map() danach

Array.from(src, fn) allokiert ein Array, Array.from(src).map(fn) allokiert zwei. Bei großen Quellen messbar. Bei kleinen wurst — Lesbarkeit entscheidet.

String → Array iteriert pro Codepoint, nicht Code-Unit

Array.from('a😀b') liefert ['a', '😀', 'b'] — drei Elemente, Surrogate-Pairs korrekt zusammengehalten. 'a😀b'.split('') würde die zwei UTF-16-Units des Emojis trennen — vier Elemente, davon zwei kaputt.

Mapper hat zweites Argument: index

Der Mapper-Callback bekommt (value, index) — wie bei Array.prototype.map. Das ist die Basis für den length-Trick: (_, i) => i + 1 nutzt nur den Index, ignoriert den (undefined-)Wert.

Set wird durch Array.from de-dupliziert? Nein — Set IST schon dedupliziert

Array.from(new Set([1, 2, 2, 3])) liefert [1, 2, 3] — nicht weil Array.from dedupliziert, sondern weil das Set selbst keine Duplikate erlaubt. Das macht Set + Array.from zum idiomatischen Dedup-Pattern: Array.from(new Set(arr)).

HTMLCollection ist NICHT iterable — Array.from nötig

document.getElementsByTagName('div') liefert eine HTMLCollection. Sie ist Array-Like (length + Index), aber NICHT iterable (kein Symbol.iterator). Daher: [...col] schlägt fehl, Array.from(col) klappt. NodeList dagegen ist iterable.

Array.fromAsync seit ES2024 — Baseline 2024

Die asynchrone Variante akzeptiert AsyncIterables und synchrone Iterables, deren Werte Promises sein können. Im Inline-Mapper kann ebenfalls await stehen. Praktisch für Stream-Pipelines (Web Streams, async generators).

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Arrays

Zur Übersicht