ES6 Spread and Rest (...)

The three dots ... in JavaScript can represent two different concepts:

  • Spread Operator – expands data
  • Rest Pattern / Rest Parameters – gathers data

They look identical but behave in opposite directions depending on where they’re used.


Concept Overview

Feature Purpose Context
Spread (...) Expands an iterable into individual elements When passing or copying data
Rest (...) Collects multiple elements into one array/object When receiving or destructuring data

Think:

🔹 Spread = explode
🔹 Rest = gather


Spread Operator

The Spread Operator is used to unpack elements from arrays, strings, or objects.

Expanding an Array

1
2
const arr = [1, 2, 3];
console.log(...arr); // 1 2 3

Copying Arrays

1
2
3
const numbers = [1, 2, 3];
const copy = [...numbers];
console.log(copy); // [1, 2, 3]

Creates a shallow copy (nested objects still share reference).


Merging Arrays

1
2
3
4
const fruits = ["APPLE", "BANANA"];
const veggies = ["CARROT", "CROCOLI"];
const food = [...fruits, ...veggies];
console.log(food); // ["APPLE", "BANANA", "CARROT", "BROCOLI"]

Adding Elements

1
2
3
const base = [2, 3];
const extended = [1, ...base, 4];
console.log(extended); // [1, 2, 3, 4]

Spreading Strings (Iterables)

1
2
const chars = [..."hello"];
console.log(chars); // ["h", "e", "l", "l", "o"]

Copying and Merging Objects (ES2018+)

1
2
3
4
5
6
7
8
const user = { name: "Alice", age: 25 };
const clone = { ...user };
console.log(clone); // { name: "Alice", age: 25 }

const defaults = { theme: "light", fontSize: 14 };
const userSettings = { theme: "dark" };
const settings = { ...defaults, ...userSettings };
console.log(settings); // { theme: "dark", fontSize: 14 }

Later spreads overwrite earlier ones.


Adding / Overriding Properties in Objects

1
2
3
4
const person = { name: "Sophy", age: 21 };
const updated = { ...person, age: 22, country: "Malaysia" };
console.log(updated);
// { name: "Sophy", age: 22, country: "Malaysia" }

Spread in Function Calls

1
2
3
4
5
function sum(a, b, c) {
return a + b + c;
}
const nums = [1, 2, 3];
console.log(sum(...nums)); // 6

Equivalent to sum(1, 2, 3).


Rest Parameters (in Functions)

Used in function parameter lists to gather all remaining arguments into an array.

Example 1: Collecting Arguments

1
2
3
4
5
6
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}

console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20, 30)); // 60

...numbers collects all arguments into a single array, and name that array numbers.


Example 2: Mixing Fixed + Rest Parameters

1
2
3
4
5
6
7
8
function introduce(firstName, ...hobbies) {
console.log(`Hi, I’m ${firstName}`);
console.log(`I like: ${hobbies.join(", ")}`);
}

introduce("Sophy", "piano", "coding", "reading");
// Hi, I’m Sophy
// I like: piano, coding, reading

firstName takes the first argument.
...hobbies gathers the rest into an array.


Rules:

  • The rest parameter must be last in the parameter list.
    1
    function bad(...nums, x) {} // ❌ SyntaxError
  • Can only appear once in a function parameter list.

Rest Pattern (in Destructuring)

Used to collect the remaining elements after destructuring an array or object.


Example 1: Array Destructuring

1
2
3
4
const [a, b, ...others] = [1, 2, 3, 4, 5];
console.log(a); // 1
console.log(b); // 2
console.log(others); // [3, 4, 5]

a and b get the first two elements.
...others gathers the remaining ones.


Example 2: Object Destructuring

1
2
3
4
5
6
7
8
9
10
11
const person = {
name: "Emulisy",
age: 22,
country: "Malaysia",
hobby: "Piano"
};

const { name, ...restInfo } = person;

console.log(name); // "Emulisy"
console.log(restInfo); // { age: 22, country: "Malaysia", hobby: "Piano" }

restInfo collects the remaining key-value pairs.


Example 3: Nested Destructuring

1
2
3
4
5
6
7
8
9
10
const data = {
id: 1,
user: { first: "Sophy", last: "Lee" },
stats: { score: 95, level: 3 }
};

const { user, ...otherData } = data;

console.log(user); // { first: "Sophy", last: "Lee" }
console.log(otherData); // { id: 1, stats: { score: 95, level: 3 } }

Combining Spread + Rest

They often appear together when copying or modifying arrays/objects.

Example (Immutability in React)

1
2
3
4
const student = { name: "Sophy", age: 21 };
const updated = { ...student, age: 22, city: "Melbourne" };
console.log(updated);
// { name: "Sophy", age: 22, city: "Melbourne" }

Example (Destructuring then Spreading)

1
2
3
4
5
6
const [first, ...rest] = [10, 20, 30, 40];
console.log(first); // 10
console.log(rest); // [20, 30, 40]

const newArr = [first, ...rest];
console.log(newArr); // [10, 20, 30, 40]

Summary

Feature Symbol Direction Example
Spread Operator ... Expands / Unpacks [...arr] → separate values
Rest Pattern ... Gathers / Packs [a, ...rest] → array of leftovers
Rest Parameter ... Gathers function args function f(...args)