Two JavaScript operators with same syntax but totally different working.
Spread
Spread operator(...
) is a tool in modern JavaScript that is used when working with arrays, objects, and function calls. Spread allows objects and iterables (arrays for now) to be unpacked.
Too techie? Spread helps us expand iterables into individual elements.
Spread with Arrays
Using spread with arrays, is something that you'll see almost every time. So focus!
const tools = ['hammer', 'screwdriver']
const otherTools = ['wrench', 'saw']
const allTools = [...tools, ...otherTools]
console.log(allTools)
//Output : ['hammer', 'screwdriver', 'wrench', 'saw']
In the example above, we see that we can unpack elements from array into another array.
This is super useful in cases, where we want to achieve immutability
, like in React Applications.
Spread with Objects
Like arrays, spread is used to copy and update objects. This was earlier done using Object.assign()
, but spread make it simple.
const ogObject = { language: 'english', darkMode: false }
const newObject = {...ogObject}
console.log(newObject)
//Output: {language: 'english', darkMode: false}
Similar to arrays, this creates a shallow copy, and the nested objects inside (if there are any) will still be passed by reference.
Spread shines when we have to add or modify properties on an existing object without mutating it.
const player = {
id: 2,
name: 'Abhi',
}
const updatedPlayer = { ...player, isLoggedIn: true }
console.log(updatedPlayer)
//Output: {id: 2, name: 'Abhi', isLoggedIn: true}
One Important concept to remember with spread and nested objects is, when copying object, remember to spread the nested objects as well.
const player = {
id: 2,
name: 'Abhi',
team: {
name: 'Avengers',
city: 'LA',
}
}
If the player is now the leader of the team and you want to update that inside the team
property, which itself is an object.
Doing this is wrong
const updatedPlayer = { ...player, team: {position: 'captain'} }
This will result in
updatedPlayer ->
id: 2,
name: 'Abhi',
team: { position: 'captain' }
See how the old fields are overwritten, to do it without mutating we have to
const updatedPlayer = {
...player, //copy entire player Object
team: {
...player.team, //copy entire player.team Object
position: 'captain',//and then update/add a property on top of old properties
}
}
Spread in Function Calls
Let's define a simple function that take 3 parameters and adds them
function addThree(a, b, c){
return a + b + c ;
}
To pass the values individually to the function call, you can do this:
addThree(2, 4, 6)
//output
//10π
Suppose you have an array that has the values that you want to pass. You can do something like this:
const nums = [2, 4, 5 ]
addThree(nums[0], nums[1], num[2])
But this is not very efficient. Instead, you can use the spread operator to spread the elements of the nums array as individual arguments to the addThree function:
addThree(...nums)
This allows us to pass the values individually, shortening our code and increasing its readability
Note: The spread operator creates a shallow copy of an array or object, meaning that any top-level properties will be cloned, but any nested objects or arrays will still be passed by reference. This is important to keep in mind when using the spread operator to make copies of objects that contain nested objects or arrays.
Rest
The rest operator (...) is used to represent an indefinite number of arguments as an array. It is usually used in function definitions to allow the function to accept any number of arguments.
function sum(...nums) {
let result = 0;
for (const num of nums) {
result += num;
}
return result;
}
console.log(sum(1, 2, 3, 4));
// Output: 10
This was done earlier using the arguments
variable, but it cannot be used with newer arrow functions and additionally arguments
is not a true array so map and filter doesnt apply on it.
Rest to destructure Arrays and Objects
Destructuring Arrays with Rest
Here's an example of using the rest operator to destructure an array:
const numbers = [1, 2, 3, 4, 5];
const [first, second, ...others] = numbers;
console.log(first);
// Output: 1
console.log(second);
// Output: 2
console.log(others);
// Output: [3, 4, 5]
Destructuring Objects with Rest
You can also use the rest operator to destructure objects. Here's an example:
const person = {
name: 'John',
age: 30,
occupation: 'developer',
location: 'New York'
};
const { name, age, ...otherInfo } = person;
console.log(name);
// Output: 'John'
console.log(age);
// Output: 30
console.log(otherInfo);
// Output: { occupation: 'developer', location: 'New York' }
In the example above, the rest operator is used to assign the remaining properties of the person
object to the otherInfo
variable.
tl;dr:
While the rest operator collects an indefinite number of arguments into an array, the spread operator extracts elements from an array (or properties from an object) and expands them into individual elements or properties.
Be sure not to confuse function parameters and function arguments:
function foo (...bar) {} // rest
foo(...baz) // spread
There's also rest in destructuring, which should not be confused with literal spreading:
const { a, b, ...others } = { a:1, b:2, c:3, d:4, e:5 } // rest
const aToE = { a, b, ...others } // spread
Destructuring is used to create varibles from array items or object properties.
Spread syntax is used to unpack iterables such as arrays, objects, and function calls.
Overall, the spread and rest operators are useful tools for working with arrays, objects, and function arguments in JavaScript. They can help you write more concise and readable code. Visit MDN if you ever want to learn more
Top comments (9)
Am I missing something or should the references to
...user
andupdatedPlayer
actually beplayer
andupdatedUser
inconst player = {
id: 2,
name: 'Abhi',
}
const updatedPlayer = { ...user, isLoggedIn: true }
console.log(updatedUser)
?
I have corrected the typo
Thanks for the heads up, much appreciated.
πβ€οΈ
Π‘ongratulations π₯³! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up π
Didn't know this till I saw your comment, thanks a lot.
Awesome post. Thank you.
I am glad it helped.
I think this post is also extendable to Python 3.x version in which they have introduced the same. Great explanation.
Glad it helped