Array.from() vs spread syntax
JavascriptArraysEcmascript 6Javascript Problem Overview
Is there some difference between using Array.from(document.querySelectorAll('div'))
or [...document.querySelectorAll('div')]
?
Here is a example:
let spreadDivArray = [...document.querySelectorAll('div')];
console.log(spreadDivArray);
let divArrayFrom = Array.from(document.querySelectorAll('div'));
console.log(divArrayFrom);
The console.log()
will log the same result.
Is there any performance difference?
Javascript Solutions
Solution 1 - Javascript
Spread element (it's not an operator) works only with objects that are iterable (i.e. implement the @@iterator
method). Array.from()
works also on array-like objects (i.e. objects that have the length
property and indexed elements) which are not iterable. See this example:
const arrayLikeObject = { 0: 'a', 1: 'b', length: 2 };
// This logs ['a', 'b']
console.log(Array.from(arrayLikeObject));
// This throws TypeError: arrayLikeObject[Symbol.iterator] is not a function
console.log([...arrayLikeObject]);
Also, if you just want to convert something to array, I think it's better to use Array.from()
because it's more readable. Spread elements are useful for example when you want to concatenate multiple arrays (['a', 'b', ...someArray, ...someOtherArray]
).
Solution 2 - Javascript
Well, Array.from
is a static method, i.e., a function whereas the spread
syntax is part of the array literal syntax. You can pass functions around like data, you can invoke them once, several times or not at all. This isn't possible with the spread
syntax, which is static in this regard.
Another difference, which @nils has already pointed out, is that Array.from
also works with array-like objects, which don't implement the iterable protocol. spread
on the other hand requires iterables.
Solution 3 - Javascript
The difference is that spread allows an array to be expanded. Whereas from()
creates a new array. .from()
doesn't expand upon anything, it creates a new array based on the data provided; the spread operator on the other hand can expand an array with new properties.
Solution 4 - Javascript
If the input is iterable they do the exact same thing.
However, based on the benchmarks, the spread operator seems to perform better for a Set.
let set = new Set();
for (let i = 0; i < 10000; i++) {
set.add(Math.random());
}
let tArrayFrom = window.performance.now()
let arr = Array.from(set)
console.log("Array.from():", window.performance.now() - tArrayFrom + "ms")
// slightly faster in most of the runs:
let tSpread = window.performance.now()
let arr2 = [...set];
console.log("Spread syntax:", window.performance.now() - tSpread + "ms")
Solution 5 - Javascript
Using Babel is a good way to see what's happening internally.
Heads up, though. Make sure latest is selected in Babel, as the default is wrong.
Using your example above, this is the output.
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
var spreadDivArray = [].concat(_toConsumableArray(document.querySelectorAll('div')));
console.log(spreadDivArray);
var divArrayFrom = Array.from(document.querySelectorAll('div'));
console.log(divArrayFrom);
Solution 6 - Javascript
I need to clarify everyone's answers:
- The
...foo
syntax just spreads (expands) all array values as if they were separate, comma-separated arguments. It does a shallow spread. Any primities (numbers, strings etc) are COPIED and any complex values (objects) are instead REFERENCED. - The
[]
around it is what CREATES a new array. - So
[...foo]
will create a new array and populate it by doing a SHALLOW COPY spreading of all array elements as if they were array constructor arguments which in turn takes all those copied elements and puts them in the new array. - Whereas
Array.from(foo)
will CREATE a new array using the input variable, but is A LOT FASTER because it ONLY creates a SHALLOW COPY (this is FASTER). So it takes the exact input and just puts every variable/reference into the new array. - Use
Array.from()
.