The spread and rest operators are important features introduced in ES6 (ECMAScript 2015). Both operators use three dots (...), but they serve different purposes depending on where they are used.
The spread operator expands elements from an array or properties from an object, while the rest operator collects multiple elements or values into a single array or object.
These features make JavaScript code shorter, cleaner, and easier to maintain. They are commonly used when copying arrays, combining objects, passing function arguments, and working with dynamic data.
What Is the Spread Operator in JavaScript?
The spread operator (...) expands the elements of an iterable, such as an array or string, or the enumerable own properties of an object into another array, object, or function call.
For example, consider the following array:
const numbers = [10, 20, 30];
console.log(...numbers);
Output:
10 20 30
The spread operator expands the array elements into separate values.
Without the spread operator, passing the array to console.log() would pass the array as a single argument. With spread syntax, each element becomes a separate argument.
Array Spread Operator
The array spread operator is useful when you want to copy arrays, combine multiple arrays, or insert existing array elements into a new array.
Copying an Array Using Spread
You can create a shallow copy of an existing array using the spread operator.
const original = [10, 20, 30];
const copy = [...original];
console.log(copy);
Output:
[10, 20, 30]
The copy array contains the same elements as the original array.
You can modify the copied array without changing the original array’s top-level elements.
const original = [10, 20, 30];
const copy = [...original];
copy.push(40);
console.log(original);
console.log(copy);
Output:
[10, 20, 30]
[10, 20, 30, 40]
The original array remains unchanged because copy is a different array.
Remember that spread creates a shallow copy. If an array contains nested objects or arrays, those nested values are still shared references.
Combining Arrays Using Spread
You can combine two or more arrays using the spread operator.
const first = [10, 20, 30];
const second = [40, 50, 60];
const combined = [...first, ...second];
console.log(combined);
Output:
[10, 20, 30, 40, 50, 60]
The spread operator expands both arrays and places their elements into a new array.
You can also add new elements while combining arrays.
const fruits = ["Apple", "Banana"];
const moreFruits = ["Mango", ...fruits, "Orange"];
console.log(moreFruits);
Output:
["Mango", "Apple", "Banana", "Orange"]
This approach is helpful when building arrays dynamically. To learn more about working with arrays, explore JavaScript Arrays.
Passing Array Elements to a Function
The spread operator can pass array elements as individual function arguments.
function add(a, b, c) {
return a + b + c;
}
const numbers = [10, 20, 30];
console.log(add(...numbers));
Output:
60
The expression add(...numbers) behaves like add(10, 20, 30).
This is useful when a function expects separate arguments but your data is stored in an array.
Object Spread Operator
The object spread syntax allows you to copy properties from one object into another object. You can also combine objects and override existing properties.
Copying an Object Using Spread
Consider the following object:
const user = {
name: "Rahul",
age: 25
};
const copiedUser = { ...user };
console.log(copiedUser);
Output:
{ name: "Rahul", age: 25 }
The spread operator copies the object’s enumerable own properties into a new object.
You can update the copied object without changing its top-level properties in the original object.
const user = {
name: "Rahul",
age: 25
};
const updatedUser = {
...user,
age: 26
};
console.log(user);
console.log(updatedUser);
Output:
{ name: "Rahul", age: 25 }
{ name: "Rahul", age: 26 }
The original object remains unchanged. The updatedUser object contains the updated age.
As with arrays, object spread creates a shallow copy. Nested objects are not cloned automatically.
Combining Objects Using Spread
You can combine properties from multiple objects into a single object.
const personalDetails = {
name: "Rahul",
age: 25
};
const professionalDetails = {
role: "Developer",
salary: 30000
};
const employee = {
...personalDetails,
...professionalDetails
};
console.log(employee);
Output:
{
name: "Rahul",
age: 25,
role: "Developer",
salary: 30000
}
The new object contains properties from both objects.
Overriding Object Properties
When multiple objects contain the same property, the value from the property written later takes precedence.
const user = {
name: "Rahul",
age: 25
};
const updatedUser = {
...user,
age: 28
};
console.log(updatedUser);
Output:
{ name: "Rahul", age: 28 }
Here, age: 28 appears after ...user, so it overrides the copied age.
The reverse order produces a different result:
const updatedUser = {
age: 28,
...user
};
console.log(updatedUser);
Output:
{ age: 25, name: "Rahul" }
The spread operation copies user.age after the initial age: 28 property, replacing it with 25.
Object spread is especially useful when updating application state, merging configuration settings, and creating modified copies of data.
What Is the Rest Operator in JavaScript?
The rest operator (...) collects multiple values into a single array or collects remaining properties into an object.
It is commonly used in function parameters and destructuring assignments.
For example:
function showNumbers(...numbers) {
console.log(numbers);
}
showNumbers(10, 20, 30, 40);
Output:
[10, 20, 30, 40]
The rest parameter collects all the arguments into an array named numbers.
Unlike the spread operator, which expands values, the rest operator gathers values together.
Rest Parameters in JavaScript Functions
Rest parameters allow a function to accept any number of arguments without requiring a fixed number of parameters.
Using Rest Parameters
Consider this example:
function addNumbers(...numbers) {
let total = 0;
for (const number of numbers) {
total += number;
}
return total;
}
console.log(addNumbers(10, 20));
console.log(addNumbers(10, 20, 30));
console.log(addNumbers(10, 20, 30, 40));
Output:
30
60
100
The function works with different numbers of arguments because the rest parameter collects them into an array.
This is useful for functions that need to process a variable number of values, such as calculating totals or finding averages.
Combining Regular Parameters with Rest Parameters
You can use regular parameters before a rest parameter.
function introduce(role, ...skills) {
console.log("Role:", role);
console.log("Skills:", skills);
}
introduce("Developer", "JavaScript", "React", "SQL");
Output:
Role: Developer
Skills: ["JavaScript", "React", "SQL"]
The first argument is assigned to role, while all remaining arguments are collected into the skills array.
Important: A rest parameter must be the last parameter in a function definition.
Correct syntax:
function example(first, ...remaining) {
console.log(first);
console.log(remaining);
}
Incorrect syntax:
// SyntaxError: rest parameter must be last
function example(...remaining, last) {
console.log(remaining, last);
}
Using Rest Parameters with Arrow Functions
Rest parameters also work with arrow functions.
const multiplyNumbers = (...numbers) => {
return numbers.reduce((total, number) => total * number, 1);
};
console.log(multiplyNumbers(2, 3, 4));
Output:
24
The rest parameter collects the arguments into an array, and the reduce() method multiplies the values together.
You can learn more about arrow function syntax and behavior in JavaScript Arrow Functions.
Rest Syntax in Array Destructuring
The rest syntax can collect the remaining elements of an array during destructuring.
const numbers = [10, 20, 30, 40, 50];
const [first, second, ...remaining] = numbers;
console.log(first);
console.log(second);
console.log(remaining);
Output:
10
20
[30, 40, 50]
The variables first and second receive the first two elements. The rest syntax collects all remaining elements into the remaining array.
The rest element must be the last element in an array destructuring pattern.
Rest Syntax in Object Destructuring
The rest syntax can also collect the remaining properties of an object.
const employee = {
name: "Priya",
age: 24,
role: "Developer",
city: "Hyderabad"
};
const { name, ...details } = employee;
console.log(name);
console.log(details);
Output:
Priya
{ age: 24, role: "Developer", city: "Hyderabad" }
The name property is assigned to the name variable. The remaining properties are collected into a new object called details.
This is useful when extracting selected properties while keeping the rest of an object’s data together.
Spread vs Rest in JavaScript
Although spread and rest use the same three-dot syntax, they perform opposite operations.
| Feature | Spread Operator | Rest Operator |
|---|---|---|
| Main purpose | Expands values | Collects values |
| Common usage | Arrays, objects, function calls | Function parameters, destructuring |
| Result in array examples | Individual elements are expanded | Remaining elements become an array |
| Result in object examples | Properties are copied into another object | Remaining properties become an object |
| Example | [...numbers] | function test(...numbers) {} |
Spread Operator Example
const numbers = [10, 20, 30];
const copy = [...numbers];
console.log(copy);
Output:
[10, 20, 30]
The spread operator expands the array elements into a new array.
Rest Operator Example
function display(...numbers) {
console.log(numbers);
}
display(10, 20, 30);
Output:
[10, 20, 30]
The rest parameter collects the function arguments into an array.
Easy Way to Remember
Think of spread as unpacking and rest as gathering.
- Spread: Takes values out of an array or object and places them into another expression.
- Rest: Gathers multiple values or remaining properties into one variable.
The exact role of ... depends on its position and the syntax surrounding it.
Common Mistakes to Avoid
Confusing Spread and Rest
The same syntax does not mean both operators do the same job. Look at where ... appears to determine its purpose.
const values = [1, 2, 3];
const copy = [...values]; // Spread
function collect(...values) { // Rest
return values;
}
Assuming Spread Creates a Deep Copy
Spread creates a shallow copy, not a complete independent copy of nested objects.
const original = {
name: "Rahul",
address: {
city: "Hyderabad"
}
};
const copy = { ...original };
copy.address.city = "Vijayawada";
console.log(original.address.city);
Output:
Vijayawada
The nested address object is shared between the original and copied objects. Changing it through copy also affects original.
Placing the Rest Parameter Incorrectly
A rest parameter must be the final parameter in a function declaration.
function calculate(first, ...others) {
console.log(first, others);
}
This is valid. Placing another parameter after ...others causes a syntax error.
Forgetting Property Override Order
When combining objects, later properties override earlier properties with the same key.
const result = {
...{ color: "red" },
...{ color: "blue" }
};
console.log(result.color);
Output:
blue
Always check the order in which properties are spread into an object.
Frequently Asked Questions
What is the difference between spread and rest in JavaScript?
Spread expands array elements or object properties into another expression. Rest collects multiple values or remaining properties into a single array or object.
Can the spread operator copy an array?
Yes. You can use [...array] to create a shallow copy of an array. Nested objects and arrays are still shared references.
Can the spread operator merge objects?
Yes. You can combine objects using { ...object1, ...object2 }. If both objects contain the same property, the later value overrides the earlier value.
Why are rest parameters useful?
Rest parameters allow functions to accept a variable number of arguments. JavaScript collects those arguments into an array, making them easy to process.
Can spread and rest be used with arrow functions?
Yes. Spread can pass array elements as individual function arguments, and rest parameters can collect arguments inside an arrow function.
Is the rest operator always written at the end?
A rest parameter must be last in a function’s parameter list. Rest syntax must also appear last in array or object destructuring patterns, where applicable.
Conclusion
The spread and rest operators simplify many common JavaScript tasks. Spread expands array elements and object properties, while rest collects multiple values or remaining properties into a single variable.
Use spread when copying or combining arrays and objects, and use rest when handling a variable number of function arguments or extracting remaining values during destructuring. Understanding the difference will help you write cleaner, more flexible JavaScript code.