Spread Operators vs Rest Parameters in Javascript
Spread syntax (…) is a new feature in ES6. It’s super useful for programmers, as it is more readable and more functional.
Table of Content
—Introduction
— Spread Operator
— Rest Parameter
— Conclusion
Introduction
Alright, spread syntax(…). What are you? A lot of you may have already heard of it, since it is one of the most used features, and possibly one of the new ES6 features you would encounter the most. The three dots have two use:
- Spread Operator
Spread operator is useful when using something iterable, like an array expression or string to be expanded without mutating. If you still don’t understand, no worries, I’ll dive deep into the functionality of spread operator in a bit.
I personally like spread operator and have been using here and there. In this article, we would discuss the difference with the pre-ES6 methods.
2. Rest Parameter
I have to be honest, I haven’t had a chance to use rest parameter as a Javascript novice. But I found it super interesting and I’d like to include this in my article. Rest parameter is an improved way to handle function parameter. With the help of a rest parameter, a function can be called indefinite numbers of arguments. It doesn’t matter how it defines.
Oof *insert Jake Peralta’s voice* chills literal chills!! I am so excited to get into this learning journey with you guys!!
Spread Operator
- … vs concat()
// concat()
let someEastCoastStates = ["Connecticut", "New York", "Virginia"]
let someEastCoastStates2 = ["Massachusetts", "New Hampshire", "Pennsylvania"]someEastCoastStates = someEastCoastStates.concat(someEastCoastStates2)console.log(someEastCoastStates)
// ["Connecticut", "New York", "Virginia", "Massachusetts", "New Hampshire", "Pennsylvania"]
// …
let someEastCoastStates = ["Connecticut", "New York", "Virginia"]
let someEastCoastStates2 = ["Massachusetts", "New Hampshire", "Pennsylvania"]someEastCoastStates = [...someEastCoastStates, ...someEastCoastStates2]// someEastCoastStates is now ["Connecticut", "New York", "Virginia", "Massachusetts", "New Hampshire", "Pennsylvania"]
Saved a lot of trouble to type that concat()!
Or we can do reversely:
someEastCoastStates = [...someEastCoastStates2, ...someEastCoastStates]// someEastCoastStates is now ["Massachusetts", "New Hampshire", "Pennsylvania", "Connecticut", "New York", "Virginia"]
2. Copy Array
let someWestCoastStates = ["Washington", "Oregon", "California", "Arizona"]
let someWestCoastStates2 = someWestCoastStatessomeWestCoastStates2
// ["Washington", "Oregon", "California", "Arizona"]
What if we want to add an element to our newly copied array?
someWestCoastStates2.push("Nevada")console.log(someWestCoastStates2)
// ["Washington", "Oregon", "California", "Arizona", "Nevada"]
// yay it worked! But wait, hold on! Let's check our original arrayconsole.log(someWestCoastStates)
// ["Washington", "Oregon", "California", "Arizona", "Nevada"]
// Um Esqueeze me???
This is not the situation we want, since we only want to change our newly copied array. This is why spread operator would come in handy.
let someWestCoastStates = ["Washington", "Oregon", "California", "Arizona"]let someWestCoastStates2 = [...someWestCoastStates]someWestCoastStates2.push("Nevada")// someWestCoastStates2 is now ["Washington", "Oregon", "California", "Arizona", "Nevada"]
// someWestCoastStates is not mutated at all.
Using spread operator would ensure that the original array would not be mutated.
3. Expand the Array
Normally, in order to expand the array, we would do:
let peanutCharacters = ["charlie brown", "snoopy", "sally brown"]
let morePeanutCharacters = [peanutCharacters, “peppermint patty”, “woodstock”]console.log(morePeanutCharacters)
// [["charlie brown", "snoopy", "sally brown"], “peppermint patty”, “woodstock”]
So… it’s an array inside of an array, which creates a multidimensional array… Hm. Well, spread operator is a good option to help us solve the problem for us.
let peanutCharacters = ["charlie brown", "snoopy", "sally brown"]let morePeanutCharacters = [“peppermint patty”, ...peanutCharacters, “woodstock”]
// you could even put the array into the desired position of your new array!console.log(morePeanutCharacters)
// ["peppermint patty", "charlie brown", "snoopy", "sally brown", "woodstock"]console.log(peanutCharacters)
// ["charlie brown", "snoopy", "sally brown"] yep, not mutated at all
Basically, you can see the three-dot is doing its magic for us without writing too much, or getting too complicated to read for other programmers.
Quick Note 1: Spread operators can also be used in Object literal {}
which is a new feature in ES2018!
let peanutsComicFact = {
1: Woodstock was first seen in the strip in 1967 but was named in 1970 after the summer music festival,
2: Snoopy's brother Spike is from Needles, California
}let peanutsComicFact2 = {
3: The Little Red Haired Girl was real,
4: Charles Schulz had to argue that the very first Peanuts animated special (A Charlie Brown Christmas) did not have a laugh track added to it. The producers didn't like it, but it became an instant hit
}let mergedPeanutsComicFactObj = { ...peanutsComicFact, ...peanutsComicFact2 }
Object {
1: Woodstock was first seen in the strip in 1967 but was named in 1970 after the summer music festival,
2: Snoopy's brother Spike is from Needles, California,
3: The Little Red Haired Girl was real,
4: Charles Schulz had to argue that the very first Peanuts animated special (A Charlie Brown Christmas) did not have a laugh track added to it. The producers didn't like it, but it became an instant hit
}
You can also destructure it!
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }
console.log(x) // 1
console.log(y) // 2
console.log(z) // { a: 3, b: 4}
Quick Note 2: Make sure the object that spread operators are used on is iterable. Objects themselves are not iterable:
let obj = { 'key': 'value' }
let array = [...obj] // TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
Rest Parameter
Sometimes when we are writing a function, we want to include as many arguments as we can, but what if we got lazy, just kidding (or am I? 🤪) or we don’t know how many arguments we need to take for a function. That’s when rest parameter becomes super handy in this case.
Without rest parameter:
function fun(a, b) {
return a + b
}console.log(fun(1, 2)) // 3
console.log(fun(1, 2, 3, 4, 5, 6)) // 3, because the function will only take the first two arguments.
With rest parameter:
function fun(...args) {
let sum = 0
for(let i of args) {
sum += i
}
return sum
}console.log(fun(1, 2)) // 3
console.log(fun(1, 2, 3)) // 6
console.log(fun(1, 2, 3, 4, 5, 6)) // 21
Conclusion
I love the spread syntax. It has provided us a lot of functionalities and we can make great use out of it. Also, most importantly to all the beginners out there, like me (to this date), I personally think the spread syntax is very beginner-friendly. Instead of remembering the “complicated stuff,” like concat(), push(), etc, you might as well just use the spread operator. Jk, don’t take my words seriously! Sometimes these methods could be more useful to run big datas, but in practice, it’s always nice to work with the spread syntax to get a hand of it. I hope you enjoy my article! Who knows I might come with a more advanced version of this article in a year or so :)
Thanks for reading!
Reference
- Github Repo about ECMAScript 6
- ES6 Features: Spread Operators (along with other new ES6 features)
- JavaScript ES6: Spread Operator and Rest Parameters (Another Medium article related to this topic)
- MDN: Spread Syntax
- GeeksforGeeks: Spread Operator
- GeeksforGeeks: Rest Parameter
- Scotch.io: Javascript’s three dots ( … ): Spread vs rest operators