JavaScript
Article
By Craig Buckler

Preparing for ECMAScript 6: Destructuring Assignment

By Craig Buckler

Destructuring assignment sounds complex. It reminds me of object oriented terms such as encapsulation and polymorphism — I’m convinced they were chosen to make simple concepts appear more sophisticated!

In essence, ECMAScript 6 (ES2015) destructuring assignment allows you to extract individual items from arrays or objects and place them into variables using a shorthand syntax. Those coming from PHP may have encountered the list() function which extracts arrays into variables in one operation. ES6 takes it to another level.

Presume we have an array:

var myArray = ['a', 'b', 'c'];

We can extract these values by index in ES5:

var
  one   = myArray[0],
  two   = myArray[1],
  three = myArray[2];

// one = 'a', two = 'b', three = 'c'

ES6 destructuring permits a simpler and less error-prone alternative:

var [one, two, three] = myArray;

// one = 'a', two = 'b', three = 'c'

You can ignore certain values, e.g.

var [one, , three] = myArray;

// one = 'a', three = 'c'

or use the spread operator (...) to extract remaining elements:

var [one, ...two] = myArray;

// one = 'a', two = ['b, 'c']

Destructuring also works on objects, e.g.

var myObject = {
  one:   'a',
  two:   'b',
  three: 'c'
};

// ES5 example
var
  one   = myObject.one,
  two   = myObject.two,
  three = myObject.three;

// one = 'a', two = 'b', three = 'c'

// ES6 destructuring example
var {one, two, three} = myObject;

// one = 'a', two = 'b', three = 'c'

In this example, the variable names one, two and three matched the object property names. We can also assign properties to variables with any name, e.g.

var myObject = {
  one:   'a',
  two:   'b',
  three: 'c'
};

// ES6 destructuring example
var {one: first, two: second, three: third} = myObject;

// first = 'a', second = 'b', third = 'c'

More complex nested objects can also be referenced, e.g.

var meta = {
  title: 'Destructuring Assignment',
  authors: [
    {
      firstname: 'Craig',
      lastname: 'Buckler'
    }
  ],
  publisher: {
    name: 'SitePoint',
    url: 'http://www.sitepoint.com/'
  }
};

var { 
    title: doc, 
    authors: [{ firstname: name }], 
    publisher: { url: web } 
  } = meta;

/*
  doc   = 'Destructuring Assignment'
  name  = 'Craig'
  web   = 'http://www.sitepoint.com/'
*/

This appears a little complicated but remember that in all destructuring assignments:

  • the left-hand side of the assignment is the destructuring target; the pattern which defines the variables being assigned
  • the right-hand side of the assignment is the destructuring source; the array or object which holds the data being extracted

There are a number of other caveats. First, you cannot start a statement with a curly brace because it looks like a code block, e.g.

// THIS FAILS
{ a, b, c } = myObject;

You must either declare the variables, e.g.

// THIS WORKS
var { a, b, c } = myObject;

or use parenthesis if variables are already declared, e.g.

// THIS WORKS
({ a, b, c }) = myObject;

// SO DOES THIS!
({ a, b, c } = myObject);

You should also be wary of mixing declared and undeclared variables, e.g.

// THIS FAILS
var a;
var { a, b, c } = myObject;

// THIS WORKS
var a, b, c;
({ a, b, c }) = myObject;

That’s the basics of destructuring. So when would it be useful? I’m glad you asked…

Easier Declaration

Variables can be declared without explicitly defining each value, e.g.

// ES5
var a = 'one', b = 'two', c = 'three';

// ES6
var [a, b, c] = ['one', 'two', 'three'];

Admittedly, the destructured version is longer. It’s a little easier to read although that may not be the case with more items.

Variable Value Swapping

Swapping values in ES5 requires a temporary third variable but it’s far simpler with destructuring:

var a = 1, b = 2;

// ES5 swap
var temp = a;
a = b;
b = temp;

// a = 2, b = 1

// ES6 swap back
[a, b] = [b, a];

// a = 1, b = 2

You’re not limited to two variables — any number of items can be rearranged, e.g.

// rotate left
[b, c, d, e, a] = [a, b, c, d, e];

Default Function Parameters

Presume we had a function to output our meta object:

var meta = {
  title: 'Destructuring Assignment',
  authors: [
    {
      firstname: 'Craig',
      lastname: 'Buckler'
    }
  ],
  publisher: {
    name: 'SitePoint',
    url: 'http://www.sitepoint.com/'
  }
};

prettyPrint(meta);

In ES5, it’s necessary to parse this object to ensure appropriate defaults are available, e.g.

// ES5 default values
function prettyPrint(param) {

  param = param || {};
  var
    pubTitle = param.title || 'No title',
    pubName = (param.publisher && param.publisher.name) || 'No publisher';

  return pubTitle + ', ' + pubName;

}

In ES6 we can assign a default value to any parameter, e.g.

// ES6 default value
function prettyPrint(param = {}) {

but we can then use destructuring to extract values and assign defaults where necessary:

// ES6 destructured default value
function prettyPrint(
  { 
    title: pubTitle = 'No title', 
    publisher: { name: pubName = 'No publisher' } 
  } = {}
) {

  return pubTitle + ', ' + pubName;

}

I’m not convinced this is easier to read but it is significantly shorter.

Returning Multiple Values from a Function

Functions can only return one value but that can be a complex object or multi-dimensional array. Destructuring assignment makes this more practical, e.g.

function f() {
  return [1, 2, 3];
}

var [a, b, c] = f();

// a = 1, b = 2, c = 3

For-of Iteration

Consider an array of book information:

var books = [
  {
    title: 'Full Stack JavaScript',
    author: 'Colin Ihrig and Adam Bretz',
    url: 'http://www.sitepoint.com/store/full-stack-javascript-development-mean/'
  },
  {
    title: 'JavaScript: Novice to Ninja',
    author: 'Darren Jones',
    url: 'http://www.sitepoint.com/store/leaern-javascript-novice-to-ninja/'
  },
  {
    title: 'Jump Start CSS',
    author: 'Louis Lazaris',
    url: 'http://www.sitepoint.com/store/jump-start-css/'
  },
];

The ES6 for-of is similar to for-in except that it extracts each value rather than the index/key, e.g.

for (let b of books) {
  console.log(b.title + ' by ' + b.author + ': ' + b.url);
}

Destructuring assignment provides further enhancements, e.g.

for (let {title, author, url} of books) {
  console.log(title + ' by ' + author + ': ' + url);
}

Regular Expression Handling

Regular expressions functions such as match return an array of matched items which can form the source of a destructuring assignment:

var [a, b, c, d] = 'one two three'.match(/\w+/g);

// a = 'one', b = 'two', c = 'three', d = undefined

Destructuring Assignment Support

Destructuring assignment may not revolutionize your development life but it could save some considerable typing effort!

As of end 2015, support for destructuring assignment is still incomplete. It’s available in Firefox 34+ with basic features in Safari 7.1+. Experimental support is available in Node 4.0+ if you run Node with the --harmony-destructuring flag but it’s best not to depend on it.

Until ES6 is generally available, compilers such as Babel and Traceur will translate ES6 destructuring assignments to an ES5 equivalent.

  • XTwentyThree

    Nice article!

  • WOW! Well explained, thanks!

    • Suzanne Lewis

      I am getting a salary of more than 3900 dollars each week , that is awesome. Over a year ago I was in a horrible condition , jobless and Bank account with only few bucks . Thank one of my friends showed me a way where I was able to gather my self and making average of 85 d/h. So it can change your life as it has changed mine.

      coolmath.CO.NF

      qwe…

  • Knight Yoshi

    The ES6 destructured default value example, while potentially useful, seems very convoluted. It definitely wasn’t easier to read.

Recommended
Sponsors
Get the latest in JavaScript, once a week, for free.