Getting Started with JavaScript ES6 Destructuring

Lets take a closer look at the new syntax that ES6 brings to help with more explicit variable and argument declaration and assignment. The current state of affairs is pretty straight forward: on the left hand side you have a variable name, on the right you have an expression which, among other things, can be an array: [ ] or an object literal: { }. Destructuring assignment allows us to have an expression like variable declaration on the left hand side describing which values to extract from the right hand side. Sounds a bit confusing? Lets look at the specific examples.

Array Destructuring

Lets say we have a value variable which is [1, 2, 3, 4, 5] and we want to declare variables that contain first three elements. Traditionally each variable would be declared and assigned separately like so:

var value = [1, 2, 3, 4, 5];
var el1 = value[0];
var el2 = value[1];
var el3 = value[2];

Having these variables, our original value might now be represented as [el1, el2, el3, 4, 5] and, since we don’t care at the moment about last two values, as something like [el1, el2, el3]. ES6 allows us to use this expression now on the left hand side to achieve the same declaration as above:

var value = [1, 2, 3, 4, 5];
var [el1, el2, el3] = value;

The right hand side doesn’t have to be a variable, we can omit value declaration all together:

var [el1, el2, el3] = [1, 2, 3, 4, 5];

The left hand side doesn’t have to a declaration either, you can use already declared variables:

var el1, el2, el3;
[el1, el2, el3] = [1, 2, 3, 4, 5];

This brings us to a neat little trick that was previously impossible in JavaScript with just two variables – swapping values.

[el1, el2] = [el2, el1];

Destructuring assignment can also be nested:

var value = [1, 2, [3, 4, 5]];
var [el1, el2, [el3, el4]] = value;

Returning tuples from functions in ES6 becomes more of a first class citizen and feels pretty natural:

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

var [first, second] = tuple();

You can also ignore certain elements in the array by simply omitting variables where appropriate:

var value = [1, 2, 3, 4, 5];
var [el1, , el3, , el5] = value;

This makes it really neat for example to pull values out of regular expression matches:

var [, firstName, lastName] = "John Doe".match(/^(w+) (w+)$/);

Taking it one step further, you can also specify default values:

var [firstName = "John", lastName = "Doe"] = [];

Note that this only works for undefined values. In the following example firstName and lastName will be null.

var [firstName = "John", lastName = "Doe"] = [null, null];

Spread operator is where things get really interesting. Spreads, otherwise knows as the “rest” pattern allow you to grab “remaining values” from the array. In the example below tail receives all remaining array elements which is [4, 5].

var value = [1, 2, 3, 4, 5];
var [el1, el2, el3, ...tail] = value;

Unfortunately implementation of splats in ES6 is somewhat primitive and only allows you to get the remaining elements. The following patterns, while being very useful, are not possible in ES6:

var value = [1, 2, 3, 4, 5];
var [...rest, lastElement] = value;
var [firstElement, ...rest, lastElement] = value;

Object Destructuring

Now that you have a pretty clear understanding of how array destructuring works, lets look at object destructuring. It works pretty much the same way, just for objects:

var person = {firstName: "John", lastName: "Doe"};
var {firstName, lastName} = person;

ES6 allows you to pull object properties using variable identifiers that differ from the property name they refer to. In the example below, variable name will be declared with person.firstName value.

var person = {firstName: "John", lastName: "Doe"};
var {firstName: name, lastName} = person;

What if you have a more complex, deeply nested, object? Not a problem!

var person = {name: {firstName: "John", lastName: "Doe"}};
var {name: {firstName, lastName}} = person;

You can throw in some array destructuring here as well:

var person = {dateOfBirth: [1, 1, 1980]};
var {dateOfBirth: [day, month, year]} = person;

And the other way around:

var person = [{dateOfBirth: [1, 1, 1980]}];
var [{dateOfBirth}] = person;

Just like when dealing with arrays you can also specify default values.

var {firstName = "John", lastName: userLastName = "Doe"} = {};

This also only works for undefined values. In the following example firstName and lastName will be null.

var {firstName = "John", lastName = "Doe"} = {firstName: null, lastName: null};

Destructuring Function Arguments

Function arguments in ES6 could also be declared in a destructuring way. This comes in super useful for the ever prolific options argument. You can use array and object destructuring together.

function findUser(userId, options) {
  if (options.includeProfile) ...
  if (options.includeHistory) ...
}

Same looks and feels much better in ES6:

function findUser(userId, {includeProfile, includeHistory}) {
  if (includeProfile) ...
  if (includeHistory) ...
}

Bottom Line

ES6 destructuring brings in much needed syntax modernizations to JavaScript. It improves readability and reduces amount of code necessary to for expressive declarations.

ES6 Today

How can you take advantage of ES6 features today? Using transpilers in the last couple of years has become the norm. People and large companies no longer shy away. Babel is an ES6 to ES5 transpiler that supports all of the ES6 features.

If you are using something like Browserify in your JavaScript build pipeline, adding Babel transpilation takes only a couple of minutes. There is, of course, support for pretty much every common Node.js build system like Gulp, Grunt and many others.

What About The Browsers?

The majority of browsers are catching up on implementing new features but not one has full support. Does that mean you have to wait? It depends. It’s a good idea to begin using the language features that will be universally available in 1-2 years so that you are comfortable with them when the time comes. On the other hand, if you feel the need for 100% control over the source code, you should stick with ES5 for now.