DEV Community

Cover image for You don't know spread operator !
Valentin PARSY
Valentin PARSY

Posted on

You don't know spread operator !

I was recently reading a blog post about iteration from Axel Rauschmayer (I suggest you follow him, all his posts are minegold for JS devs).
This post was mindblowing to me as I learned so much about iteratables in JavaScript.

Let's challenge our knowledge

Let me sum up a bit of what I learned here with a small challenge to you :
When I use the spread operator on a Number, I want the result to be an array that counts from 1 to the given value :
Example in the chrome console

First steps to an answer

First thing to do is try the code for yourself and you will see that using a spread operator on a Number throws an error => Uncaught TypeError: X is not iterable

Then what is an iterable ?
An iterable is an object that defines an iteration behavior, meaning it has a property with a Symbol.iterator key and an iterator as value.
This iterator should respect the iteration protocol which means it is a function that returns an object with a next fonction that returns an object with 2 properties : "value" (the current iteration's value) and "done" (a boolean indicating weither we are done iterating with this iterator or not).

The spread operator is simply a consummer of such iterables: when you give it an iterable, it'll call the next function of its Symbol.iterator property until it returns an object with {done: true} (and push each time the result in an array).

Verify that with an Array

An array in JavaScript is an iterable since it has an iterator as a value of its property with Symbol.iterator key.
Here is how you can use this iterator :
Usage of an array iterator in the chrome console

Answer to the challenge

So how do I make the spread operator not throwing an error when given a number ? You set the Symbol.iterator property on the Number primitive wrapper object.
Let's make all numbers iterables !
Setting the property on the Number's prototype


Obviously you never want to change the prototype of a primitive wrapper object, it's too dangerous.
But the knowledge of how iteration and the spread operator works is I think very valuable as a developper.

Discussion (5)

sadanandpai profile image
Akshay Pai

Very simple if used generator

Number.prototype[Symbol.iterator] = function* () {
for (let i = 1; i <= this; i++) yield i;

parsyvalentin profile image
Valentin PARSY Author

Exactly, I wanted to keep this simple for people not knowing anything about this subject (like me 2 weeks ago =D )
But from there you can go absolutely nuts ! The sky is the limit ! You can actually declare the iteration protocol inside a class, then all your "instances" are iterables.

ca0v profile image
Corey Alix

Why is it dangerous?

parsyvalentin profile image
Valentin PARSY Author

The Number primitive wrapper object is used EVERYWHERE. If you change anything that "low-level" in your code, it will change it everywhere in your code/app, potentially changing the behavior of (in this example) every Number you use.

As a solution you could have your own IterableNumber, that is a Number to which you set the Symbol.iterator property. (not sure it is a good solution though)

loclv profile image

I think there are a case to be made teammate (include me) confused.

a = 8
// output 🚀: [1, 2, 3]

// now set it's value again
a = 's'
// output 🚀: ['s']
Enter fullscreen mode Exit fullscreen mode