Array.from() vs spread syntax

JavascriptArraysEcmascript 6

Javascript 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.

https://jsben.ch/5lKjg

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().

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjotavejvView Question on Stackoverflow
Solution 1 - JavascriptMichał PerłakowskiView Answer on Stackoverflow
Solution 2 - Javascriptuser6445533View Answer on Stackoverflow
Solution 3 - JavascriptJames DonnellyView Answer on Stackoverflow
Solution 4 - JavascriptAminView Answer on Stackoverflow
Solution 5 - JavascriptKeithView Answer on Stackoverflow
Solution 6 - JavascriptMitch McMabersView Answer on Stackoverflow