Post cover

5 Handy Applications of JavaScript Array.from()

Posted August 27, 2019

Any programming language has functions that go beyond the basic usage. It happens thanks to a successful design and a wide area of problems it tries to solve.

One such function in JavaScript is the Array.from(): a workhorse allowing lots of useful transformations on JavaScript collections (arrays, array-like objects, iterables like string, maps, sets, etc).

In this post, I will describe 5 use cases of Array.from() that are both useful and interesting.

Before I go on, let me recommend something to you.

The path to becoming good at JavaScript isn't easy... but fortunately with a good teacher you can shortcut.

Take "Modern JavaScript From The Beginning 2.0" course by Brad Traversy to become proficient in JavaScript in just a few weeks. Use the coupon code DMITRI and get your 20% discount!

1. Quick introduction

Before starting, let's recall what Array.from() does. Here's how you would call the function:


Array.from(arrayLikeOrIterable[, mapFunction[, thisArg]]);

It's first obligatory argument arrayLikeOrIterable is an array-like object or an iterable.

The second optional argument mapFunction(item, index) {...} is a function invoked on every item in the collection. The returned value is inserted into the new collection.

Finally, the third optional argument thisArg is used as this value when invoking mapFunction. This argument is rarely used.

For examples, let's multiply by 2 the numbers of an array-like object:


const someNumbers = { '0': 10, '1': 15, length: 2 };
Array.from(someNumbers, value => value * 2); // => [20, 30]

2. Transform array-like into an array

The first useful application of Array.from() is indicated directly from its definition: transform an array-like object into an array.

Usually, you meet these strange creatures array-like objects as arguments special keyword inside of a function, or when working with DOM collections.

In the following example, let's sum the arguments of a function:


function sumArguments() {
return Array.from(arguments).reduce((sum, num) => sum + num);
}
sumArguments(1, 2, 3); // => 6

Array.from(arguments) transforms the array-like arguments into an array. The new array is reduced to the sum of its elements.

Moreover, you can use Array.from() with any object or primitive that implements the iterable protocol. Let's see a few examples:


Array.from('Hey'); // => ['H', 'e', 'y']
Array.from(new Set(['one', 'two'])); // => ['one', 'two']
const map = new Map();
map.set('one', 1)
map.set('two', 2);
Array.from(map); // => [['one', 1], ['two', 2]]

3. Clone an array

There is a tremendous number of ways to clone an array in JavaScript.

As you might expect, Array.from() easily shallow copies an array:


const numbers = [3, 6, 9];
const numbersCopy = Array.from(numbers);
numbers === numbersCopy; // => false

Array.from(numbers) creates a shallow copy of numbers array. The equality check numbers === numbersCopy is false, meaning that while having the same items, these are different array objects.

Is it possible to use Array.from() to create a clone of the array, including all the nested ones? Challenge accepted!


function recursiveClone(val) {
return Array.isArray(val) ? Array.from(val, recursiveClone) : val;
}
const numbers = [[0, 1, 2], ['one', 'two', 'three']];
const numbersClone = recursiveClone(numbers);
numbersClone; // => [[0, 1, 2], ['one', 'two', 'three']]
numbers[0] === numbersClone[0] // => false

recursiveClone() creates a deep clone of the supplied array. This is achieved by calling recursively recursiveClone() on array items that are arrays too.

Can you write a shorter than mine version of recursive clone that uses Array.from()? If so, please write a comment below!

4. Fill an array with values

In case if you need to initialize an array with the same values, Array.from() is at your service too.

Let's define a function that creates an array filled with the same default values:


const length = 3;
const init = 0;
const result = Array.from({ length }, () => init);
result; // => [0, 0, 0]

result contains a new array having 3 items initialized with zeros. This is done by invoking Array.from() with an array-like object { length }, and a map function that returns the initialization value.

However, there is an alternative method array.fill() that can be used to achieve the same result:


const length = 3;
const init = 0;
const result = Array(length).fill(init);
fillArray2(0, 3); // => [0, 0, 0]

fill() method fills the array correctly with initialization values, regardless of empty slots.

4.1 Fill an array with new objects

When every item of the initialized array should be a new object, Array.from() is a better solution:


const length = 3;
const resultA = Array.from({ length }, () => ({}));
const resultB = Array(length).fill({});
resultA; // => [{}, {}, {}]
resultB; // => [{}, {}, {}]
resultA[0] === resultA[1]; // => false
resultB[0] === resultB[1]; // => true

resultA created by Array.from() is initialized with different instances of empty objects {}. It happens because the map function () => ({}) on every invocation returns a new object.

However, resultB created by fill() method is initialized with the same instance of an empty object.

4.2 What about array.map()?

Is it possible to use array.map() method to achieve the same? Let's try that:


const length = 3;
const init = 0;
const result = Array(length).map(() => init);
result; // => [undefined, undefined, undefined]

The map() approach seems to be incorrect. Instead of the expected array with three zeros, an array with 3 empty slots is created.

It happens because Array(length) creates an array having 3 empty slots (also called sparse array), but map() method skips the iteration over these empty slots.

5. Generate ranges of numbers

You can use Array.from() to generate ranges of values. For example, the following function range generates an array with items starting 0 until end - 1:


function range(end) {
return Array.from({ length: end }, (_, index) => index);
}
range(4); // => [0, 1, 2, 3]

Inside range() function, Array.from() is supplied with the array-like { length: end }, and a map function that simply returns the current index. This way you can generate ranges of values.

6. Unique items of an array

A nice trick resulting from the ability of Array.from() to accept iterable objects is to quickly remove duplicates from an array. It is achieved in combination with Set data structure:


function unique(array) {
return Array.from(new Set(array));
}
unique([1, 1, 2, 3, 3]); // => [1, 2, 3]

At first, new Set(array) creates a set containing the items of the array. Internally, the set removes the duplicates.

Because the set is iterable, Array.from() extracts the unique items into a new array.

7. Conclusion

Array.from() static method accepts array-like objects, as well as iterables. It accepts a mapping function. Moreover, the function does not skip iteration over empty holes. This combination of features gives Array.from() a lot of possibilities.

As presented above, you can easily transform array-like objects to arrays, clone arrays, fill arrays with initial values, generates ranges and remove duplicated array items.

Indeed, Array.from() is a combination of good design, configuration flexibility allowing a wide area of collection transformations.

What other interesting use cases of Array.from() do you know? Please write a comment below!

Like the post? Please share!

Dmitri Pavlutin

About Dmitri Pavlutin

Software developer and sometimes writer. My daily routine consists of (but not limited to) drinking coffee, coding, writing, overcoming boredom 😉. Living in the sunny Barcelona. 🇪🇸