ES6 Destructuring

What is destructuring?

The destructuring assignment syntax is a JavaScript expression in ES6 that makes it possible to extract data from arrays or objects using a syntax that mirrors the construction of array and object literals.

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[0];

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

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;

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) ...
  }

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

Be first to comment

Leave a Reply