Spread and Rest Operators
The spread (...) operator expands elements, while the rest operator collects elements into an array. Same syntax, different contexts.
Spread Operator
Array Spreading
javascriptconst arr1 = [1, 2, 3]; const arr2 = [4, 5, 6]; // Combine arrays const combined = [...arr1, ...arr2]; console.log(combined); // [1, 2, 3, 4, 5, 6] // Copy array const copy = [...arr1]; console.log(copy); // [1, 2, 3] // Add elements const extended = [...arr1, 4, 5, ...arr2]; console.log(extended); // [1, 2, 3, 4, 5, 4, 5, 6]
Object Spreading
javascriptconst obj1 = { a: 1, b: 2 }; const obj2 = { c: 3, d: 4 }; // Merge objects const merged = { ...obj1, ...obj2 }; console.log(merged); // { a: 1, b: 2, c: 3, d: 4 } // Override properties const updated = { ...obj1, b: 10, e: 5 }; console.log(updated); // { a: 1, b: 10, e: 5 } // Copy object const objCopy = { ...obj1 }; console.log(objCopy); // { a: 1, b: 2 }
Function Arguments
javascriptfunction sum(a, b, c) { return a + b + c; } const numbers = [1, 2, 3]; console.log(sum(...numbers)); // 6 // Math functions const nums = [5, 2, 8, 1, 9]; console.log(Math.max(...nums)); // 9 console.log(Math.min(...nums)); // 1 // Array methods const arr = [1, 2, 3]; const newArr = [0, ...arr, 4]; console.log(newArr); // [0, 1, 2, 3, 4]
Rest Operator
Function Parameters
javascript// Collect remaining arguments function multiply(multiplier, ...numbers) { return numbers.map(num => num * multiplier); } console.log(multiply(2, 1, 2, 3, 4)); // [2, 4, 6, 8] // First parameter + rest function greet(greeting, ...names) { return names.map(name => `${greeting}, ${name}!`); } console.log(greet('Hello', 'Alice', 'Bob', 'Charlie')); // ['Hello, Alice!', 'Hello, Bob!', 'Hello, Charlie!']
Array Destructuring
javascriptconst colors = ['red', 'green', 'blue', 'yellow', 'purple']; // First few elements + rest const [primary, secondary, ...otherColors] = colors; console.log(primary); // 'red' console.log(secondary); // 'green' console.log(otherColors); // ['blue', 'yellow', 'purple'] // Skip elements const [first, , third, ...remaining] = colors; console.log(first); // 'red' console.log(third); // 'blue' console.log(remaining); // ['yellow', 'purple']
Object Destructuring
javascriptconst user = { name: 'John', age: 30, city: 'NYC', country: 'USA', occupation: 'Developer' }; // Extract specific properties + rest const { name, age, ...details } = user; console.log(name); // 'John' console.log(age); // 30 console.log(details); // { city: 'NYC', country: 'USA', occupation: 'Developer' }
Practical Examples
javascript// Clone and modify arrays const originalTodos = [ { id: 1, text: 'Learn JavaScript', done: false }, { id: 2, text: 'Build a project', done: true } ]; const newTodo = { id: 3, text: 'Deploy app', done: false }; const updatedTodos = [...originalTodos, newTodo]; // Remove item from array const todoIdToRemove = 1; const filteredTodos = originalTodos.filter(todo => todo.id !== todoIdToRemove); // Update object in array const updatedTodoList = originalTodos.map(todo => todo.id === 2 ? { ...todo, done: false } : todo ); // Function with flexible parameters function createApiUrl(baseUrl, endpoint, ...params) { let url = `${baseUrl}/${endpoint}`; if (params.length > 0) { url += '?' + params.join('&'); } return url; } console.log(createApiUrl('https://api.example.com', 'users', 'page=1', 'limit=10')); // 'https://api.example.com/users?page=1&limit=10' // State management pattern const initialState = { user: null, loading: false, error: null }; function updateState(currentState, updates) { return { ...currentState, ...updates }; } const newState = updateState(initialState, { user: { name: 'Alice' }, loading: true }); console.log(newState); // { user: { name: 'Alice' }, loading: true, error: null }
Common Patterns
javascript// Convert NodeList to Array const divs = document.querySelectorAll('div'); const divArray = [...divs]; // Remove duplicates from array const numbersWithDuplicates = [1, 2, 2, 3, 3, 4]; const uniqueNumbers = [...new Set(numbersWithDuplicates)]; console.log(uniqueNumbers); // [1, 2, 3, 4] // Flatten array (one level) const nestedArray = [[1, 2], [3, 4], [5, 6]]; const flattened = [].concat(...nestedArray); console.log(flattened); // [1, 2, 3, 4, 5, 6] // Function composition with rest/spread function pipe(value, ...functions) { return functions.reduce((acc, fn) => fn(acc), value); } const addOne = x => x + 1; const double = x => x * 2; const result = pipe(5, addOne, double); // (5 + 1) * 2 = 12