Sent out once every month. No spam.
In javascript, spread operator is denoted by … (3 dots), basically it takes an array or object or string and can copy or expand or concat or merge its items to another variable.
And we will not be looking into rest parameters which looks similar to spread operator but used for destructuring array and objects.
var str = 'Hello World';
console.log(...str); // H e l l o W o r l d
var obj = { name: 'My Car', modelYear: '2018' };
var obj2 = { model: 'Ferrari' };
console.log({ ...obj, obj2 }); // { "name": "My Car", "modelYear": "2018", "model": "Ferrari" }
var arr = [1, 2, 3, 4, 5];
console.log(...arr); // 1 2 3 4 5
First, we will see its pros and cons and how it works then we will implement it. Let us start with the cons.
.apply() method to pass multiple parameters.Now we have an idea of what spread operator is and what it can and can't do. Let's implement our custom spread operator step by step.
// This is how our Custom Spread Operator will look like
console.log([...5]); // [1, 2, 3, 4, 5]
// Above custom spread operator will not work now and
// We will get the following error
// Uncaught TypeError: number 5 is not iterable (cannot read property Symbol(Symbol.iterator))
Array, Sets, Maps, Objects, arguments and DOM{:html} (Eg: NodeList) etc,.Symbol.iterator called Iterable.Iterator to iterate the values passed to it.var myCustomIterator = {
[Symbol.iterator]: function () {},
};
Simple right? 😆
Note: By default functions are not iterable.
In the below example, we will create a simple iterable function to understand more.
// A simple function which will accept a parameter called `n`
// and it return myCustomIterator.
var generateNumbers = function (n) {
var myCustomIterator = {
[Symbol.iterator]: function () {
var i = 1; // Statement 1
return {
next: () => {
return {
value: i++, // Statement 3
done: i === n + 2, // Statement 2
};
},
};
},
};
return myCustomIterator;
};
generateNumbers(); // return an iterable function
generateNumbers() function upon calling it return an object.next() and it in turn return an object with two properties called value & done.next() will be called on each iteration.value property as third statement in for loop (Eg: for (statement 1; statement 2; i++)).done property as second statement in for loop (Eg: for (statement 1; i === n + 2; i++))To make sure our generateNumbers() is iterable we will use for of and spread operator loop in below example:
for (var i of generateNumbers(5)) {
console.log(i); // prints from 1 to 5
}
// It works 😆
// Now we can do this
[...generateNumbers(5)]; // prints from 1 to 5
// TADA 😁
Cool right? We made a function iterable.
In our next and final step, we will make generateNumbers() as a native feature so that we can do this [...5] instead of [...generateNumbers(5)].
// Add Symbol.iterator to Number prototype
Number.prototype[Symbol.iterator] = function () {
var i = 1; // Statement 1
return {
next: () => {
return {
value: i++, // Statement 3
done: i === this + 2, // Statement 2
};
},
};
};
// Now I can do this 🤪
console.log([...5]); // [1, 2, 3, 4, 5]
Thanks to TC39 committee and ES6 specs, we were able to write our own custom iterator function with spread operator. Would love to know how you are going to use Symbol.iterator now that you have learned about it.
If you liked it tweet about it. Hoping you learned something new about javascript today. My next post is how a virtual DOM works. And if you are not subscribed, subscribe below :D