1

There are these two ES6-methods of creating an array from an array-like or iterable object:

  1. Array.from(): let arr = Array.from(Object);
  2. Spread syntax: let arr = [...Object];

Here are both in action doing exactly the same:

let string = 'foobar';

console.log( [...string] );
console.log( Array.from(string) );

What is the difference between the two and which one should I use preferably to convert a HTMLCollection to an array?

leonheess
  • 16,068
  • 14
  • 77
  • 112
  • 2
    https://www.measurethat.net/Benchmarks/Show/1721/0/arrayfrom-vs-spread – User863 Jul 29 '19 at 11:13
  • @chrispbacon that's backwards. Transpilers will convert syntax for you but they *won't* automagically add a polyfill for global methods. – Jared Smith Jul 29 '19 at 11:14
  • 1
    `Array.from` is likely to give you more compatibility with older browsers. What I mean by this, take `querySelectorAll`, it's an array like collection. When `Symbol.iterator()` was introduced it was likely implemented straight away for this, but what about `Element.classList` it returns a `DOMTokenList`, but some browsers vendors might not have implemented the iterator for it straight away. Saying all this it's likely that most class A browsers now have iterators implemented for everything that it makes sense for. But if you plan running on older browser it might be wise to check. – Keith Jul 29 '19 at 11:43

2 Answers2

2

Update for 2022

Most of us don't have to support IE anymore, and it matters a lot less which one you use than it used to because there's less potential for the kind of bug I describe below to slip through to production.

Original answer

There isn't much difference in terms of what each does (except in a few contrived scenarios), but you should almost certainly use the spread syntax. The reason is that syntax will automatically be converted by babel, the Typescript compiler, etc. but you'll need to add a polyfill for Array.from unless you just don't care about older browsers. In general prefer compile/build-time solutions to run-time solutions.

Jared Smith
  • 19,721
  • 5
  • 45
  • 83
  • You'd include polyfills anyway to use newer features. Babel just adds its own `arrayFrom` polyfill and calls that when you use spread syntax. – Bergi Jul 29 '19 at 11:26
  • @Bergi yes but if you're using babel/typescript it will do it for you, and there's no way to forget. I work sometimes on projects where I have to support older browsers but mostly projects where I don't and I'm not in the habit of automatically including core in my builds. – Jared Smith Jul 29 '19 at 11:30
  • I'd specify that, "There isn't a difference in terms of what each does..." _in this specific case_. There's absolutely a difference between them, as stated in other comments & answers (i.e. there are cases where `...` won't work). In many contexts, this has nothing to do with run-time vs compile-time & the OP didn't mention Babel. – Lovethenakedgun Apr 21 '22 at 06:42
  • @Lovethenakedgun the examples where Array.from works but spread fails are, for the most part, contrived (see my comments on Keith's answer). As for the babel/compile-time thing, I wrote this answer 3 years ago, when a **lot** of devs still had to support IE. Babel/tsc can compile spread down to ES5 easily enough and will do so without any further intervention on the part of the dev. But if you don't include a polyfill it is entirely possible to push code that uses Array.from and passes all the tests but then your prod error logs blow up. But now that most of us don't have to support a... – Jared Smith Apr 21 '22 at 11:05
  • ....decade old browser and Babel isn't automatically included in almost every single project? Meh. Maybe you're right. Updated. And above should say "comments with Keith on ellipsis' answer). – Jared Smith Apr 21 '22 at 11:07
2

Spread syntax only works with objects that implement the iterator method (Symbol.iterator()).

Array.from() on the other hand will also work on array-like objects(indexed elements) which do not implement the iterable method.

Array.from() can be used for HTML collections because of the readability as the results for both will be same in this case.

ellipsis
  • 12,049
  • 2
  • 17
  • 33
  • Can you give an example of an indexed collection works with one but not the other? Besides a contrived one like `{ a: 1, b: 2, length: 1 }` I mean. – Jared Smith Jul 29 '19 at 11:17
  • @JaredSmith I assume you meant something like -> `{0: 'zero', 1: 'one', length: 2}`, although contrived does actually show you the difference. – Keith Jul 29 '19 at 11:28
  • @Keith yes, wasn't thinking when I wrote that. – Jared Smith Jul 29 '19 at 11:32