Before discussing object rest and spread properties, let’s take a trip down memory lane and remind ourselves of a very similar feature.
ES2015 array rest and spread elements #
Good ol’ ECMAScript 2015 introduced rest elements for array destructuring assignment and spread elements for array literals.
const primes = [2, 3, 5, 7, 11];
const [first, second, ...rest] = primes;
console.log(first);
console.log(second);
console.log(rest);
const primesCopy = [first, second, ...rest];
console.log(primesCopy);
- Chrome: supported since version 47
- Firefox: supported since version 16
- Safari: supported since version 8
- Node.js: supported since version 6
- Babel: supported
ES2018: object rest and spread properties 🆕 #
So what’s new, then? Well, a proposal enables rest and spread properties for object literals, too.
const person = {
firstName: 'Sebastian',
lastName: 'Markbåge',
country: 'USA',
state: 'CA',
};
const { firstName, lastName, ...rest } = person;
console.log(firstName);
console.log(lastName);
console.log(rest);
const personCopy = { firstName, lastName, ...rest };
console.log(personCopy);
Spread properties offer a more elegant alternative to Object.assign()
in many situations:
const data = { x: 42, y: 27, label: 'Treasure' };
const clone1 = Object.assign({}, data);
const clone2 = { ...data };
const defaultSettings = { logWarnings: false, logErrors: false };
const userSettings = { logErrors: true };
const settings1 = Object.assign({}, defaultSettings, userSettings);
const settings2 = { ...defaultSettings, ...userSettings };
However, there are some subtle differences in how spreading handles setters:
Object.assign()
triggers setters; spread doesn’t.- You can stop
Object.assign()
from creating own properties via inherited read-only properties, but not the spread operator.
Axel Rauschmayer’s write-up explains these gotchas in more detail.
- Chrome: supported since version 60
- Firefox: supported since version 55
- Safari: supported since version 11.1
- Node.js: supported since version 8.6
- Babel: supported