Quiz

What are the benefits of using spread syntax in JavaScript and how is it different from rest syntax?

Topics
JavaScript
Edit on GitHub

TL;DR

Spread syntax (...) allows an iterable (like an array or string) to be expanded into individual elements. This is often used as a convenient and modern way to create new arrays or objects by combining existing ones.

OperationTraditionalSpread
Array cloningarr.slice()[...arr]
Array mergingarr1.concat(arr2)[...arr1, ...arr2]
Object cloningObject.assign({}, obj){ ...obj }
Object mergingObject.assign({}, obj1, obj2){ ...obj1, ...obj2 }

Rest syntax is the opposite of what spread syntax does. It collects a variable number of arguments into an array. This is often used in function parameters to handle a dynamic number of arguments.

// Using rest syntax in a function
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // Output: 6

Spread syntax

ES2015's spread syntax is very useful when coding in a functional paradigm as we can easily create copies of / merge arrays or objects without resorting to Object.create, Object.assign, Array.prototype.slice, or a library function. This language feature is used often in Redux and RxJS projects.

Copying arrays/objects

The spread syntax provides a concise way to create copies of arrays or objects without modifying the originals. This is useful for creating immutable data structures. However do note that arrays copied via the spread operator are shallowly-copied.

// Copying arrays
const array = [1, 2, 3];
const newArray = [...array];
console.log(newArray); // Output: [1, 2, 3]
// Copying objects
const obj = { name: 'John', age: 30 };
const newObj = { ...person, city: 'New York' };
console.log(newObj); // Output: { name: 'John', age: 30, city: 'New York' }

Merging arrays/objects

The spread syntax allows you to merge arrays or objects by spreading their elements/properties into a new array or object.

// Merging arrays
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const mergedArray = [...arr1, ...arr2];
console.log(mergedArray); // Output: [1, 2, 3, 4, 5, 6]
// Merging objects
const obj1 = {
foo: 'bar',
};
const obj2 = {
qux: 'baz',
};
const merged = { ...obj1, ...obj2 };
console.log(copyOfTodd); // Output: { foo: "bar", qux: "baz" }

Passing arguments to functions

Use the spread syntax to pass an array of values as individual arguments to a function, avoiding the need for apply().

const numbers = [1, 2, 3];
Math.max(...numbers); // Same as Math.max(1, 2, 3)

Array vs object spreads

Only iterable values like Arrays and Strings can be spread in an array. Trying to spread non-iterables will result in a TypeError.

Spreading object into array:

const person = {
name: 'Todd',
age: 29,
};
const array = [...person]; // Error: Uncaught TypeError: person is not iterable

On the other hand, arrays can be spread into objects.

const array = [1, 2, 3];
const obj = { ...array }; // { 0: 1, 1: 2, 2: 3 }

Rest syntax

The rest syntax (...) in JavaScript allows you to represent an indefinite number of elements as an array or object. It is like an inverse of the spread syntax, taking data and stuffing it into an array rather than unpacking an array of data, and it works in function arguments, as well as in array and object destructuring assignments.

Rest parameters in functions

The rest syntax can be used in function parameters to collect all remaining arguments into an array. This is particularly useful when you don't know how many arguments will be passed to the function.

function addFiveToABunchOfNumbers(...numbers) {
return numbers.map((x) => x + 5);
}
const result = addFiveToABunchOfNumbers(4, 5, 6, 7, 8, 9, 10);
console.log(result); // Output: [9, 10, 11, 12, 13, 14, 15]

Provides a cleaner syntax than using the arguments object, which is unsupported for arrow functions and represents all arguments whereas the usage of the rest syntax below allows remaining to represent the 3rd argument and beyond.

const [first, second, ...remaining] = [1, 2, 3, 4, 5];
console.log(first); // Output: 1
console.log(second); // Output: 2
console.log(remaining); // Output: [3, 4, 5]

Note that the rest parameters must be at the end. The rest parameters gather all remaining arguments, so the following does not make sense and causes an error:

function addFiveToABunchOfNumbers(arg1, ...numbers, arg2) {
// Error: Uncaught Rest element must be last element.
}

Array destructuring

The rest syntax can be used in array destructuring to collect the remaining elements into a new array.

const [a, b, ...rest] = [1, 2, 3, 4]; // a: 1, b: 2, rest: [3, 4]

Object destructuring

The rest syntax can be used in object destructuring to collect the remaining properties into a new object.

const { e, f, ...others } = {
e: 1,
f: 2,
g: 3,
h: 4,
}; // e: 1, f: 2, others: { g: 3, h: 4 }

Further Reading

Edit on GitHub