- read

JavaScript Array.from in Depth

The Software Line 60

JavaScript Array.from in Depth

Complete overview of important detail about Array.from method

The Software Line
Level Up Coding
Published in
3 min readApr 3

--

Photo by Ryan Riggins on Unsplash

The idea of this article is to show all the variations on Array.from() static method usage. So, let’s start.

1. First argument must be array-like object or iterable

An array-like is an object. It has indexed access to the elements and a non-negative length property to know the number of elements in it.
These are the only similarities it has with an array. Doesn’t have any of the Array methods like, push, pop, join, map, etc. Objects that have indexed properties and length are called array-like. Such objects may also have other properties and methods, but lack the built-in methods of arrays.

The iterable is an interface that specifies that an object can be accessible if it implements a method who is key is [symbol.iterator].

Some of the built-in data structure that use iterable are :

  • Arrays
  • Strings
  • Maps
  • Sets

When you invoke Array.from() with something which is not array-like object or iterable, you will not get any error, but just an empty array as the result.

So, Array.from() method static method creates a new, shallow-copied Array instance from an iterable or array-like object.

Let’s put all together. Below you can find the examples with non-array-like objects (object and number), array-like object and iterables
(Map, Set, String and Array):

// non array-like objects
const user = { id: 1, username: 'John' };
console.log(Array.from(user)) // []

const number = 123
console.log(Array.from(number)); // []

// array like object
const arrayLikeObject = {
0: 'cat',
1: 'cat',
2: 'cow',
length: 3
}

console.log(Array.from(arrayLikeObject)) // ['cat', 'dog', 'cow']

// iterables
const map = new Map([
["apples", 500],
["bananas", 300],
["oranges", 200]
])
console.log(Array.from(map))
// [ [ 'apples', 500 ], [ 'bananas', 300 ], [ 'oranges', 200 ] ]

const set = new Set([1, 2, 3]);
console.log(Array.from(set));
// [ 1, 2, 3 ]

const str = "foo";
console.log(Array.from(str));
// [ 'f', 'o', 'o' ]

const arr = [1, 2, 3, 4];
console.log(Array.from(arr))
// [1, 2, 3, 4]

// convert NodeList to array
const nodeList = document.querySelectorAll('...');
const nodes = Array.from(nodeList);

2. Usage with mapper function

The second (optional) parameter of Array.from() method is the mapper function, which accepts the current element from the array and also the index.

const data = new Set([1, 1, 2, 3]);
const mapFn = (value, index) => value * 2;
console.log(Array.from(data, mapFn));
// result: [2, 4, 6]

3. Usage with specified array length and mapper function

It is possible to set the array length inside the array-like object which is the first argument of the method and use the map function to set the default value for each initial element inside the array.

const data = Array.from({ length: 5 }, (value, index) => {
console.log(value, index); // value=undefined, index=0,1,2,3,4
return null;
});
console.log(data);
// result: [null, null, null, null, null]

4. Method creates shallow-copied new array

A shallow copy of an Array copies only the elements of the Array, whether they are reference types or value types, but it does not copy the objects that the references refer to. For deep copy you can use JSON.parse(JSON.stringify()) or structuredClone() method.

const a = [
{
name: 'John',
surname: 'Doe',
location: {
city: 'LA'
}
}
]

const b = Array.from(a);
const [first] = b;
first.name = 'Mark'
first.location.city = 'Chicago'

console.log('a: ', a)
console.log('b: ', b);

// result:
a:
[
{
"name": "Mark",
"surname": "Doe",
"location": {
"city": "Chicago"
}
}
]

b:
[
{
"name": "Mark",
"surname": "Doe",
"location": {
"city": "Chicago"
}
}
]

const c = [1, 2, 3];
const d = Array.from(c);
d[0] = 2;

// result:
c:
[
1,
2,
3
]

d:
[
2,
2,
3
]

As you can see, both arrays are changed when we have objects inside (reference types).

Conclusion

We have a lot of variations on Array.from method usage, so we need to choose the best option for specific case. Remember that method creates shallow-copied new Array without deep copy.

Thanks for reading.
I hope you enjoyed the article and learned something.