Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
95 lines (78 sloc) 3.2 KB
title author avatars date tags tweet
Object rest and spread properties
Mathias Bynens ([@mathias](https://twitter.com/mathias))
mathias-bynens
2017-06-06
ECMAScript
ES2018
890269994688315394

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 { #array-rest-spread }

Good ol’ ECMAScript 2015 introduced rest elements for array destructuring assignment and spread elements for array literals.

// Rest elements for array destructuring assignment:
const primes = [2, 3, 5, 7, 11];
const [first, second, ...rest] = primes;
console.log(first); // 2
console.log(second); // 3
console.log(rest); // [5, 7, 11]

// Spread elements for array literals:
const primesCopy = [first, second, ...rest];
console.log(primesCopy); // [2, 3, 5, 7, 11]

ES2018: object rest and spread properties 🆕 { #object-rest-spread }

So what’s new, then? Well, a proposal enables rest and spread properties for object literals, too.

// Rest properties for object destructuring assignment:
const person = {
    firstName: 'Sebastian',
    lastName: 'Markbåge',
    country: 'USA',
    state: 'CA',
};
const { firstName, lastName, ...rest } = person;
console.log(firstName); // Sebastian
console.log(lastName); // Markbåge
console.log(rest); // { country: 'USA', state: 'CA' }

// Spread properties for object literals:
const personCopy = { firstName, lastName, ...rest };
console.log(personCopy);
// { firstName: 'Sebastian', lastName: 'Markbåge', country: 'USA', state: 'CA' }

Spread properties offer a more elegant alternative to Object.assign() in many situations:

// Shallow-clone an object:
const data = { x: 42, y: 27, label: 'Treasure' };
// The old way:
const clone1 = Object.assign({}, data);
// The new way:
const clone2 = { ...data };
// Either results in:
// { x: 42, y: 27, label: 'Treasure' }

// Merge two objects:
const defaultSettings = { logWarnings: false, logErrors: false };
const userSettings = { logErrors: true };
// The old way:
const settings1 = Object.assign({}, defaultSettings, userSettings);
// The new way:
const settings2 = { ...defaultSettings, ...userSettings };
// Either results in:
// { logWarnings: false, logErrors: true }

However, there are some subtle differences in how spreading handles setters:

  1. Object.assign() triggers setters; spread doesn’t.
  2. 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.

You can’t perform that action at this time.