Using the spread operator ... you can expand an array, an object or a string. It allows an iterable such as an array or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Let’s start with an array example:

const a = [1, 2, 3];

you can create a new array using a

const a = [1, 2, 3];

const b = [...a, 4, 5, 6];

console.log(b);
// expected output: [1, 2, 3, 4, 5, 6]

You can also create a shallow copy of an array using it

const a = [1, 2, 3];

const c = [...a];

console.log(c);
// expected output: [1, 2, 3]

This works for objects as well. You can shallow copy an object with:

const oldObj = { test: 'testing' };

const newObj = { ...oldObj };

console.log(newObj);
// expected output: { test: 'testing' }

Using strings, the spread operator creates an array with each char in the string, like the split() with an empty string:

const hey = 'hey';
const arrayized = [...hey];

console.log(arrayized);
// expected output: ['h', 'e', 'y']

console.log(hey.spli(''));
// expected output: ['h', 'e', 'y']

This operator has some pretty useful applications. One of the most important is the ability to use an array as function argument in a very simple way by spreading it:

const sum = (x, y, z) => x + y + z;

const numbers = [1, 2, 3];

console.log(f(...numbers));
// expected output: 6

The rest element is useful when working with array destructuring:

const numbers = [1, 2, 3, 4, 5];

const [first, second, ...others] = numbers;

console.log(first);
// expected output: 1

console.log(second);
// expected output: 2

console.log(others);
// expected output: [3, 4, 5]

and spread elements like the example before:

const numbers = [1, 2, 3, 4, 5];

const sum = (a, b, c, d, e) => a + b + c + d + e

console.log(sum(...numbers));
// expected output: 15

ES2018 introduces rest properties, which are the same but for objects.

Rest properties:

const { first, second, ...others } = {
  first: 1,
  second: 2,
  third: 3,
  fourth: 4,
};

console.log(first);
// expected output: 1

console.log(second);
// expected output: 2

console.log(others);
// expected output: { third: 3, fourth: 4 }

Spread properties allow to create a new object by combining the properties of the object passed after the spread operator:

const items = { first, second, ...others };

console.log(items);
// expected output: { first: 1, second: 2, third: 3, fourth: 4 }

It is also the perfect way to merge two simple objects into one:

const object1 = {
  name: 'Toncho',
};

const object2 = {
  website: 'https://toncho.dev',
};

const object3 = {...object1, ...object2 };

console.log(object3);
// expected output: { name: 'Toncho', website: 'https://toncho.dev' }