Array.prototype.from()
Array.from(arrayLike, mapFn?, thisArg?) Array.from() creates a new shallow-copied Array instance from an array-like or iterable object. It provides a consistent way to convert various data structures into arrays, which is essential since many JavaScript APIs return array-like objects that lack array methods.
Syntax
Array.from(arrayLike)
Array.from(arrayLike, mapFn)
Array.from(arrayLike, mapFn, thisArg)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
arrayLike | ArrayLike or Iterable | - | An array-like or iterable object to convert |
mapFn | function | undefined | Optional map function to apply to each element |
thisArg | any | undefined | Value to use as this when executing mapFn |
Examples
Converting a string to an array
const str = "hello";
const chars = Array.from(str);
console.log(chars);
// ['h', 'e', 'l', 'l', 'o']
Splitting a string gives you each character as a separate array element, making Array.from() the simplest way to turn a string into a character list. The mapFn parameter—the second argument to Array.from()—lets you apply a transformation during the same conversion pass, avoiding a separate .map() chain afterward.
Using the map function
const nums = [1, 2, 3];
const doubled = Array.from(nums, n => n * 2);
console.log(doubled);
// [2, 4, 6]
// Equivalent to:
console.log(nums.map(n => n * 2));
// [2, 4, 6]
When you pass a mapping function, Array.from() calls it once per element as it builds the array. This is more efficient than converting first and mapping second because it makes only one pass over the data. The next example shows the most common real-world use case: converting DOM queries into arrays so you can call array methods on them.
Converting a NodeList
const paragraphs = document.querySelectorAll('p');
const paraArray = Array.from(paragraphs);
// Now you can use array methods like .map(), .filter()
NodeList objects are iterable but they are not true arrays, so methods like .map() and .filter() are not available on them directly. Converting with Array.from() is a one-liner that unblocks the full array toolkit. The same pattern works for any iterable, including Set, which also lacks direct array method access.
Creating an array from a Set
const set = new Set([1, 2, 3, 2, 1]);
const arr = Array.from(set);
console.log(arr);
// [1, 2, 3]
Converting a Set to an array is a common pattern for deduplication: Array.from(new Set(values)) strips duplicates in one expression. The method also works with plain array-like objects—anything with a length property and numeric keys—which makes it useful for generating arrays of a fixed size without writing a loop.
Creating arrays with a specific length
// Create an array of length 5 filled with zeros
const zeros = Array.from({ length: 5 }, (_, i) => 0);
console.log(zeros);
// [0, 0, 0, 0, 0]
The same pattern generates sequential numbers by using the index directly as the value. The second argument `(_, i) => i + 1` ignores the element (which is `undefined` for sparse array-likes) and uses the index to produce the sequence. This is the standard way to create numeric ranges without a for loop.
// Create an array of sequential numbers
const range = Array.from({ length: 10 }, (_, i) => i + 1);
console.log(range);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
The examples above cover the fundamental conversions: strings with mapFn, DOM nodes, Sets, and array-like length objects. The patterns below wrap Array.from() in reusable utilities that come up often in day-to-day work. Each one is short enough to keep inlined but general enough to pull into a shared module.
Common Patterns
Generating ranges
const range = (start, end) =>
Array.from({ length: end - start + 1 }, (_, i) => start + i);
console.log(range(5, 10));
// [5, 6, 7, 8, 9, 10]
Wrapping Array.from({ length }, fn) in a utility function makes range generation reusable. When cloning, keep in mind that Array.from() does a shallow copy—nested objects and arrays share references with the original. The next example shows how to handle nested structures.
Deep cloning arrays
const original = [1, [2, 3], { a: 4 }];
// Shallow copy (same as [...original])
const shallow = Array.from(original);
// For deep clone, combine with structuredClone
const deep = Array.from(original, item =>
Array.isArray(item) ? Array.from(item) : item
);
Deep cloning with Array.from() is limited to arrays of arrays. For objects, reach for structuredClone() instead. The next pattern shows a classic pre-ES6 workaround that Array.from() replaced: converting the arguments object into a real array, which used to require Array.prototype.slice.call().
Converting arguments to array (pre-ES6 pattern replacement)
function example() {
// Old way:
const args = Arrayslice.call(arguments);
// Modern way:
const args = Array.from(arguments);
}
Array.from() vs spread syntax
Both Array.from(iterable) and [...iterable] convert an iterable to an array. The difference is that Array.from accepts a mapFn second argument, which applies a transformation in the same pass as the conversion. This avoids creating an intermediate array just to call .map() on it afterward:
const set = new Set([1, 2, 3]);
// Two-step with spread
const doubled = [...set].map(x => x * 2);
// One-step with from
const doubled2 = Array.from(set, x => x * 2);
When you have an iterable and no mapping to apply, spread syntax is shorter. But Array.from is the only option for array-like objects that are not iterable—objects with length and numeric keys but no Symbol.iterator. Attempting spread on these throws a TypeError:
const arrayLike = { 0: 'a', 1: 'b', length: 2 };
Array.from(arrayLike); // ['a', 'b']
[...arrayLike]; // TypeError: not iterable
This distinction matters when you are working with the arguments object in non-arrow functions, or with objects returned by older DOM APIs like getElementsByTagName.
Creating ranges
Array.from({ length: n }, (_, i) => i) is the standard pattern for generating a range of integers. The first argument is an array-like object (any object with a length property), and the map function receives the index as its second argument:
const range = (start, end) =>
Array.from({ length: end - start }, (_, i) => start + i);
console.log(range(5, 10)); // [5, 6, 7, 8, 9]
The range utility above makes numeric sequences readable in one expression. Another everyday use for Array.from() is converting browser DOM collections—the NodeList returned by querySelectorAll and the HTMLCollection from getElementsByTagName—into real arrays so standard methods become available.
Converting DOM collections
DOM methods like querySelectorAll and getElementsByTagName return NodeList or HTMLCollection objects that are iterable but lack Array methods. Array.from converts them to real arrays so you can use map, filter, reduce, and so on:
const inputs = Array.from(document.querySelectorAll('input'));
const values = inputs.map(input => input.value);
Array.from() on strings with Unicode
Array.from() handles Unicode correctly - it splits by Unicode code points, not by UTF-16 code units. This matters for emoji and characters outside the Basic Multilingual Plane, which are represented as surrogate pairs in UTF-16. The spread operator and Array.from both use the string iterator, which iterates code points, so they agree here. This is different from String.prototype.split(''), which splits by code unit and corrupts surrogate pairs:
const emoji = '😀🎉';
Array.from(emoji); // ['😀', '🎉'] - correct
emoji.split(''); // ['\uD83D', '\uDE00', '\uD83C', '\uDF89'] - broken
Why Array.from() exists
Array.from() fills a gap between array-like values and real arrays. Many browser APIs and older JavaScript patterns produce objects that look like arrays but do not have array methods. Converting them first makes later code simpler because you can rely on map(), filter(), slice(), and reduce() without special-case handling. The method also keeps the conversion and mapping steps in one place, which can make data flow easier to read.
Array-like versus iterable
The most important distinction is that Array.from() accepts both iterables and array-like objects. Iterables are consumed through their iterator, while array-like values are read by length and numeric indexes. That is why it works on NodeList, strings, and Sets, but also on plain objects that only expose length. If you know a value is already iterable, spread syntax may be shorter. If it is only array-like, Array.from() is the right tool.