Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /Javascript
  4. /Rest Spread Operators
Your Progress0%
0 of 61 completed

JavaScript Topics

Getting Started

  • What is JavaScript?
  • JavaScript vs Other Languages
  • Setting Up Your JavaScript Environment
  • Developer Console and Debugging Basics

JavaScript Fundamentals

  • Variables (var, let, const)
  • Data Types and Type Checking
  • Comments and Code Organization
  • String Methods and Template Literals
  • Type Conversion and Coercion
  • Operators (Arithmetic, Comparison, Logical)

Control Flow

  • If/Else Statements
  • Switch Statements
  • Ternary Operator
  • Truthy and Falsy Values
  • Logical Operators and Short-Circuiting

Loops and Iteration

  • For Loops
  • While and Do-While Loops
  • For...of and For...in Loops
  • Break and Continue Statements

Functions

  • Function Declarations and Expressions
  • Arrow Functions
  • Function Parameters and Arguments
  • Return Statements and Values
  • Scope and Closures
  • Higher-Order Functions and Callbacks

Arrays

  • Array Basics and Creation
  • Array Methods: Adding and Removing Elements
  • Array Iteration Methods (forEach, map, filter)
  • Array Methods: find, some, every, reduce
  • Sorting, Reversing, and Array Transformation

Objects

  • Object Basics and Properties
  • Object Methods and 'this' Keyword
  • Object Destructuring
  • Object.keys, values, entries
  • Spread Operator and Object Cloning

DOM Manipulation

  • Introduction to the DOM
  • Selecting Elements (querySelector, getElementById)
  • Modifying Elements (textContent, innerHTML, style)
  • Creating and Removing Elements
  • Event Listeners and Event Handling
  • Event Object and Event Delegation

Asynchronous JavaScript

  • Understanding Asynchronous Code
  • setTimeout and setInterval
  • Callbacks and Callback Hell
  • Promises and Promise Chaining
  • Async/Await

Error Handling

  • Try, Catch, Finally
  • Throwing Custom Errors

Modern JavaScript Features

  • ES6+ Overview
  • Modules (import/export)
  • Optional Chaining and Nullish Coalescing
  • Rest and Spread Operators

Working with Data

  • JSON (Parse and Stringify)
  • Fetch API and HTTP Requests
  • Working with Local Storage

Advanced Concepts

  • Classes and Object-Oriented Programming
  • Array and Object Advanced Patterns
  • Regular Expressions Basics

Best Practices & Real-World Application

  • JavaScript Best Practices
  • Debugging Techniques and Tools
  • Building a Complete Interactive Project

Rest and Spread Operators

The versatile ... operator for collecting and spreading

The three dots (...) in JavaScript serve two powerful purposes: as the rest operator, it collects multiple values into an array; as the spread operator, it expands arrays and objects into individual elements. Despite using the same syntax, these operators are opposites—one gathers, one spreads. They're essential for modern JavaScript, enabling flexible function parameters, easy array/object manipulation, and clean code patterns. Let's master both uses of this versatile operator!

Spread Operator (...)

The spread operator expands (spreads) an iterable into individual elements.

1. Spreading Arrays

JAVASCRIPT
// Spreading arrays into individual elements
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];

// Old way: concat
let combined1 = arr1.concat(arr2);
console.log(combined1);  // [1, 2, 3, 4, 5, 6]

// Modern way: spread
let combined2 = [...arr1, ...arr2];
console.log(combined2);  // [1, 2, 3, 4, 5, 6]

// Mix spread with other elements
let mixed = [0, ...arr1, 3.5, ...arr2, 7];
console.log(mixed);  // [0, 1, 2, 3, 3.5, 4, 5, 6, 7]

// Spread in function calls
let numbers = [5, 3, 9, 1];
console.log(Math.max(...numbers));  // 9
// Same as: Math.max(5, 3, 9, 1)

// Old way without spread
console.log(Math.max.apply(null, numbers));  // Ugly!

2. Cloning Arrays

JAVASCRIPT
let original = [1, 2, 3];

// Wrong: This only copies the reference!
let notACopy = original;
notACopy.push(4);
console.log(original);  // [1, 2, 3, 4] - original changed!

// Correct: Spread creates a shallow clone
let copy = [...original];
copy.push(5);
console.log(original);  // [1, 2, 3, 4] - unchanged
console.log(copy);      // [1, 2, 3, 4, 5]

// Other cloning methods (all equivalent)
let copy2 = original.slice();
let copy3 = Array.from(original);
let copy4 = [...original];  // Cleanest!

// Note: Shallow clone (nested arrays still reference same objects)
let nested = [[1, 2], [3, 4]];
let shallowCopy = [...nested];
shallowCopy[0].push(99);
console.log(nested);      // [[1, 2, 99], [3, 4]] - changed!
console.log(shallowCopy); // [[1, 2, 99], [3, 4]]

3. Spreading Objects

JAVASCRIPT
// Spread object properties into new object
let person = { name: 'Alice', age: 25 };
let address = { city: 'NYC', zip: '10001' };

// Combine objects
let user = { ...person, ...address };
console.log(user);
// { name: 'Alice', age: 25, city: 'NYC', zip: '10001' }

// Clone objects
let personCopy = { ...person };
personCopy.age = 30;
console.log(person.age);      // 25 (unchanged)
console.log(personCopy.age);  // 30

// Override properties (last one wins)
let defaults = { theme: 'light', size: 'medium' };
let userPrefs = { theme: 'dark' };

let settings = { ...defaults, ...userPrefs };
console.log(settings);
// { theme: 'dark', size: 'medium' }
// userPrefs.theme overrides defaults.theme

// Add properties while spreading
let enhanced = {
  ...person,
  email: 'alice@test.com',
  active: true
};
console.log(enhanced);
// { name: 'Alice', age: 25, email: 'alice@test.com', active: true }

Spread makes code cleaner

Without Spread

// Old way: Manual copying

// Combine arrays
let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = arr1.concat(arr2);

// Clone array
let copy = arr.slice();

// Combine objects
let obj = {};
for (let key in obj1) {
  obj[key] = obj1[key];
}
for (let key in obj2) {
  obj[key] = obj2[key];
}

// Or Object.assign
let obj = Object.assign({}, obj1, obj2);

// Pass array to function
Math.max.apply(null, numbers);
Output:
Not run yet...

With Spread

// Modern way: Spread operator

// Combine arrays
let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = [...arr1, ...arr2];

// Clone array
let copy = [...arr];

// Combine objects
let obj = { ...obj1, ...obj2 };

// Clean and readable!

// Pass array to function
Math.max(...numbers);

// Much cleaner!
Output:
Not run yet...

Rest Parameter (...)

The rest parameter collects multiple arguments into an array. Same syntax, opposite purpose!

1. Function Rest Parameters

JAVASCRIPT
// Rest parameter collects all arguments into array
function sum(...numbers) {
  console.log(numbers);  // Array of all arguments
  return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3));           // 6
console.log(sum(1, 2, 3, 4, 5));     // 15
console.log(sum(10, 20, 30, 40, 50, 60));  // 210

// Old way: arguments object (not an array!)
function oldSum() {
  console.log(arguments);  // Array-like, not real array
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  return total;
}

// Rest is better: real array with array methods
function average(...numbers) {
  if (numbers.length === 0) return 0;
  let sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
}

console.log(average(10, 20, 30));  // 20

2. Rest with Named Parameters

JAVASCRIPT
// Combine named parameters with rest (rest must be last!)
function createUser(name, age, ...interests) {
  return {
    name,
    age,
    interests  // Array of remaining arguments
  };
}

let user = createUser('Alice', 25, 'coding', 'reading', 'hiking');
console.log(user);
// {
//   name: 'Alice',
//   age: 25,
//   interests: ['coding', 'reading', 'hiking']
// }

// Practical: Logger with category
function log(level, message, ...details) {
  console.log(`[${level}] ${message}`);
  if (details.length > 0) {
    console.log('Details:', details);
  }
}

log('INFO', 'User logged in');
log('ERROR', 'Database connection failed', 'timeout', 'host: db.example.com');
// [ERROR] Database connection failed
// Details: ['timeout', 'host: db.example.com']

// Must be last parameter
// function bad(name, ...rest, age) {}  // Error!
function good(name, age, ...rest) {}   // OK

3. Rest in Destructuring

JAVASCRIPT
// Array destructuring with rest
let [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first);   // 1
console.log(second);  // 2
console.log(rest);    // [3, 4, 5]

// Skip elements
let [a, , ...others] = [10, 20, 30, 40];
console.log(a);       // 10
console.log(others);  // [30, 40]

// Object destructuring with rest
let user = {
  name: 'Alice',
  age: 25,
  email: 'alice@test.com',
  city: 'NYC',
  country: 'USA'
};

let { name, age, ...otherInfo } = user;
console.log(name);      // "Alice"
console.log(age);       // 25
console.log(otherInfo); // { email: '...', city: 'NYC', country: 'USA' }

// Practical: Extract some props, keep others
function UserCard({ name, avatar, ...props }) {
  console.log('Display:', name, avatar);
  console.log('Pass to parent:', props);
}

UserCard({
  name: 'Alice',
  avatar: '/avatar.png',
  onClick: () => {},
  className: 'card',
  dataId: 123
});
// Display: Alice /avatar.png
// Pass to parent: { onClick: [Function], className: 'card', dataId: 123 }

Practical Patterns

Pattern 1: Merging Arrays

JAVASCRIPT
// Add elements to array immutably
let todos = ['Task 1', 'Task 2'];

// Add to end
let withNewTodo = [...todos, 'Task 3'];
console.log(withNewTodo);  // ['Task 1', 'Task 2', 'Task 3']

// Add to beginning
let withUrgent = ['URGENT', ...todos];
console.log(withUrgent);  // ['URGENT', 'Task 1', 'Task 2']

// Insert in middle
let index = 1;
let withInserted = [
  ...todos.slice(0, index),
  'Inserted Task',
  ...todos.slice(index)
];
console.log(withInserted);  // ['Task 1', 'Inserted Task', 'Task 2']

// Remove element immutably
let toRemove = 'Task 1';
let filtered = todos.filter(t => t !== toRemove);
// Or with spread and slice:
let removed = [...todos.slice(0, 0), ...todos.slice(1)];

Pattern 2: Merging Objects (Config/Settings)

JAVASCRIPT
// Default settings pattern
function createConfig(userConfig = {}) {
  let defaults = {
    theme: 'light',
    fontSize: 14,
    animations: true,
    notifications: true,
    language: 'en'
  };
  
  // User config overrides defaults
  return { ...defaults, ...userConfig };
}

let config1 = createConfig();
console.log(config1);  // All defaults

let config2 = createConfig({ theme: 'dark', fontSize: 16 });
console.log(config2);
// { theme: 'dark', fontSize: 16, animations: true, ... }

// API request options
function fetchData(url, customOptions = {}) {
  let defaultOptions = {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json'
    },
    timeout: 5000
  };
  
  let options = { ...defaultOptions, ...customOptions };
  
  return fetch(url, options);
}

fetchData('/api/users', {
  method: 'POST',
  body: JSON.stringify({ name: 'Alice' })
});

Pattern 3: Removing Properties

JAVASCRIPT
// Remove properties using destructuring + rest
let user = {
  id: 1,
  name: 'Alice',
  password: 'secret123',
  email: 'alice@test.com',
  role: 'admin'
};

// Remove password (don't send to client)
let { password, ...safeUser } = user;
console.log(safeUser);
// { id: 1, name: 'Alice', email: 'alice@test.com', role: 'admin' }

// Remove multiple properties
let { password: p, email: e, ...publicData } = user;
console.log(publicData);
// { id: 1, name: 'Alice', role: 'admin' }

// Function to remove specific keys
function omit(obj, ...keys) {
  let copy = { ...obj };
  keys.forEach(key => delete copy[key]);
  return copy;
}

let cleaned = omit(user, 'password', 'email');
console.log(cleaned);
// { id: 1, name: 'Alice', role: 'admin' }

Pattern 4: Function Argument Flexibility

JAVASCRIPT
// Accept variable number of arguments
function multiply(multiplier, ...numbers) {
  return numbers.map(n => n * multiplier);
}

console.log(multiply(2, 1, 2, 3));     // [2, 4, 6]
console.log(multiply(10, 5, 10, 15));  // [50, 100, 150]

// Build query strings
function buildURL(base, ...params) {
  let query = params
    .map(([key, value]) => `${key}=${value}`)
    .join('&');
  return `${base}?${query}`;
}

let url = buildURL('/api/users', ['page', 1], ['limit', 10], ['sort', 'name']);
console.log(url);  // "/api/users?page=1&limit=10&sort=name"

// Variadic math functions
function min(...numbers) {
  return numbers.reduce((min, n) => n < min ? n : min);
}

function max(...numbers) {
  return numbers.reduce((max, n) => n > max ? n : max);
}

console.log(min(5, 2, 8, 1, 9));  // 1
console.log(max(5, 2, 8, 1, 9));  // 9

Practical Examples

Example 1: Shopping Cart Operations

JAVASCRIPT
class ShoppingCart {
  constructor() {
    this.items = [];
  }
  
  // Add items (using spread)
  addItems(...newItems) {
    this.items = [...this.items, ...newItems];
  }
  
  // Remove item immutably
  removeItem(itemId) {
    this.items = this.items.filter(item => item.id !== itemId);
  }
  
  // Update item quantity
  updateQuantity(itemId, quantity) {
    this.items = this.items.map(item =>
      item.id === itemId
        ? { ...item, quantity }  // Spread + override
        : item
    );
  }
  
  // Merge carts
  mergeCarts(...otherCarts) {
    let allItems = otherCarts.reduce(
      (items, cart) => [...items, ...cart.items],
      [...this.items]
    );
    this.items = allItems;
  }
  
  // Get total
  getTotal() {
    return this.items.reduce(
      (total, item) => total + (item.price * item.quantity),
      0
    );
  }
}

let cart = new ShoppingCart();

cart.addItems(
  { id: 1, name: 'Book', price: 20, quantity: 1 },
  { id: 2, name: 'Pen', price: 2, quantity: 5 }
);

console.log(cart.items.length);  // 2

cart.updateQuantity(1, 2);  // Change book quantity to 2

console.log(cart.getTotal());  // 50 (20*2 + 2*5)

Example 2: Component Props Pattern

JAVASCRIPT
// React-style component with rest/spread
function Button({ type = 'button', children, onClick, ...restProps }) {
  // Extract specific props, pass rest to DOM element
  return {
    element: 'button',
    type,
    onClick,
    children,
    // Spread rest props (className, id, data-*, etc.)
    ...restProps
  };
}

let button = Button({
  type: 'submit',
  children: 'Submit',
  onClick: () => console.log('Clicked'),
  className: 'btn btn-primary',
  id: 'submit-btn',
  'data-testid': 'submit',
  disabled: false
});

console.log(button);
// {
//   element: 'button',
//   type: 'submit',
//   onClick: [Function],
//   children: 'Submit',
//   className: 'btn btn-primary',
//   id: 'submit-btn',
//   'data-testid': 'submit',
//   disabled: false
// }

// HOC pattern: Add props
function withLogging(Component) {
  return function LoggedComponent(props) {
    console.log('Props:', props);
    return Component(props);
  };
}

// Wrapper adds props
function withDefaults(Component, defaults) {
  return function WithDefaultsComponent(props) {
    let mergedProps = { ...defaults, ...props };
    return Component(mergedProps);
  };
}

let EnhancedButton = withDefaults(Button, {
  className: 'btn',
  type: 'button'
});

Example 3: State Management

JAVASCRIPT
// Immutable state updates with spread
class Store {
  constructor(initialState = {}) {
    this.state = initialState;
  }
  
  // Update nested state immutably
  updateUser(updates) {
    this.state = {
      ...this.state,
      user: {
        ...this.state.user,
        ...updates
      }
    };
  }
  
  // Add to array
  addTodo(todo) {
    this.state = {
      ...this.state,
      todos: [...this.state.todos, todo]
    };
  }
  
  // Remove from array
  removeTodo(todoId) {
    this.state = {
      ...this.state,
      todos: this.state.todos.filter(t => t.id !== todoId)
    };
  }
  
  // Update nested array item
  updateTodo(todoId, updates) {
    this.state = {
      ...this.state,
      todos: this.state.todos.map(todo =>
        todo.id === todoId
          ? { ...todo, ...updates }
          : todo
      )
    };
  }
  
  // Merge multiple updates
  setState(...updates) {
    this.state = Object.assign({}, this.state, ...updates);
  }
}

let store = new Store({
  user: { name: 'Alice', age: 25 },
  todos: []
});

store.updateUser({ age: 26, email: 'alice@test.com' });
console.log(store.state.user);
// { name: 'Alice', age: 26, email: 'alice@test.com' }

store.addTodo({ id: 1, text: 'Learn JavaScript', done: false });
store.addTodo({ id: 2, text: 'Build project', done: false });

store.updateTodo(1, { done: true });
console.log(store.state.todos);
// [
//   { id: 1, text: 'Learn JavaScript', done: true },
//   { id: 2, text: 'Build project', done: false }
// ]

Rest and Spread Operators

Master ... for collecting and spreading

Output:
Click "Run" to execute your code...
💡 Tip: Use console.log() to see your output in the console above.

Key Takeaways

  • ... has two uses: spread and rest (opposite purposes)
  • Spread: expands arrays/objects into individual elements
  • Use spread to clone, combine, and manipulate arrays/objects
  • [...arr] clones array, {...obj} clones object (shallow)
  • Rest: collects multiple values into an array
  • Use rest in function parameters: function(...args)
  • Use rest in destructuring: let [a, ...rest] = arr
  • Rest parameter must be last in function parameters
  • Perfect for immutable updates in state management
  • Essential for modern JavaScript patterns

What's Next?

Congratulations! You've completed the Modern JavaScript Features section and now understand rest and spread operators—the versatile ... syntax for collecting and spreading values. You've mastered both uses and know when to apply each!

You've now completed 53 out of 62 JavaScript tutorial pages (85% complete)! You've finished 12 major sections and are in the home stretch. Outstanding progress!

💪 Practice Challenge:

Before moving on, try:

  1. Clone arrays and objects using spread
  2. Combine multiple arrays/objects with spread
  3. Create a function that accepts variable arguments with rest
  4. Use rest in destructuring to extract remaining properties
  5. Build an immutable state update function using spread

Test Your Understanding

Question 1 / 4

What does the spread operator (...) do?

Score: 0 / 0

Mastering rest and spread operators in JavaScript! 🎯

Previous
Optional Chaining and Nullish Coalescing
Next
JSON (Parse and Stringify)

Continue Learning JavaScript

Join 2,000+ developers mastering JavaScript. New lessons weekly - 100% FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

JavaScript Tutorials

0 of 61 completed

Your Progress0%

Topics

Getting Started

  • What is JavaScript?
  • JavaScript vs Other Languages
  • Setting Up Your JavaScript Environment
  • Developer Console and Debugging Basics

JavaScript Fundamentals

  • Variables (var, let, const)
  • Data Types and Type Checking
  • Comments and Code Organization
  • String Methods and Template Literals
  • Type Conversion and Coercion
  • Operators (Arithmetic, Comparison, Logical)

Control Flow

  • If/Else Statements
  • Switch Statements
  • Ternary Operator
  • Truthy and Falsy Values
  • Logical Operators and Short-Circuiting

Loops and Iteration

  • For Loops
  • While and Do-While Loops
  • For...of and For...in Loops
  • Break and Continue Statements

Functions

  • Function Declarations and Expressions
  • Arrow Functions
  • Function Parameters and Arguments
  • Return Statements and Values
  • Scope and Closures
  • Higher-Order Functions and Callbacks

Arrays

  • Array Basics and Creation
  • Array Methods: Adding and Removing Elements
  • Array Iteration Methods (forEach, map, filter)
  • Array Methods: find, some, every, reduce
  • Sorting, Reversing, and Array Transformation

Objects

  • Object Basics and Properties
  • Object Methods and 'this' Keyword
  • Object Destructuring
  • Object.keys, values, entries
  • Spread Operator and Object Cloning

DOM Manipulation

  • Introduction to the DOM
  • Selecting Elements (querySelector, getElementById)
  • Modifying Elements (textContent, innerHTML, style)
  • Creating and Removing Elements
  • Event Listeners and Event Handling
  • Event Object and Event Delegation

Asynchronous JavaScript

  • Understanding Asynchronous Code
  • setTimeout and setInterval
  • Callbacks and Callback Hell
  • Promises and Promise Chaining
  • Async/Await

Error Handling

  • Try, Catch, Finally
  • Throwing Custom Errors

Modern JavaScript Features

  • ES6+ Overview
  • Modules (import/export)
  • Optional Chaining and Nullish Coalescing
  • Rest and Spread Operators

Working with Data

  • JSON (Parse and Stringify)
  • Fetch API and HTTP Requests
  • Working with Local Storage

Advanced Concepts

  • Classes and Object-Oriented Programming
  • Array and Object Advanced Patterns
  • Regular Expressions Basics

Best Practices & Real-World Application

  • JavaScript Best Practices
  • Debugging Techniques and Tools
  • Building a Complete Interactive Project
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo