Back

Destructuring assignment

Destructuring assignment

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

Syntax

[a, b] = [1, 2]
[a, b, ...rest] = [1, 2, 3, 4, 5]
{a, b} = {a:1, b:2}
{a, b, ...rest} = {a:1, b:2, c:3, d:4}  //ES7

{a, b} = {a:1, b:2} is not valid stand-alone syntax, as the {a, b} on the left-hand side is considered a block and not an object literal.

However, the ({a, b} = {a:1, b:2}) form is valid, as is the var {a, b} = {a:1, b:2} form.

Description

The object and array literal expressions provide an easy way to create ad hoc packages of data. Once you've created these packages of data, you can use them any way you want to. You can even return them from functions.

One particularly useful thing you can do with destructuring assignment is to read an entire structure in a single statement, although there are a number of interesting things you can do with them, as shown in the examples below.

This capability is similar to features present in languages such as Perl and Python.

Array destructuring

Simple example

var foo = ["one", "two", "three"];

// without destructuring
var one   = foo[0];
var two   = foo[1];
var three = foo[2];

// with destructuring
var [one, two, three] = foo;

Assignment without declaration

Destructuring assignment can be made without a declaration in the assignment statement.

var a, b;

[a, b] = [1, 2];

Swapping variables

After executing this code, b is 1 and a is 3. Without destructuring assignment, swapping two values requires a temporary variable (or, in some low-level languages, the XOR-swap trick).

var a = 1;
var b = 3;

[a, b] = [b, a];

Multiple-value returns

Thanks to destructuring assignment, functions can return multiple values. While it's always been possible to return an array from a function, this provides an added degree of flexibility.

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

As you can see, returning results is done using an array-like notation, with all the values to return enclosed in brackets. You can return any number of results in this way. In this example, f() returns the values [1, 2] as its output.

var a, b;
[a, b] = f();
console.log("A is " + a + " B is " + b);

The statement [a, b] = f() assigns the results of the function to the variables in brackets, in order: a is set to 1 and b is set to 2.

You can also retrieve the return values as an array:

var a = f();
console.log("A is " + a);

In this case, a is an array containing the values 1 and 2.

Ignoring some returned values

You can also ignore return values that you're not interested in:

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

var [a, , b] = f();
console.log("A is " + a + " B is " + b);

After running this code, a is 1 and b is 3. The value 2 is ignored. You can ignore any (or all) returned values this way. For example:

[,,] = f();

Pulling values from a regular expression match

When the regular expression exec() method finds a match, it returns an array containing first the entire matched portion of the string and then the portions of the string that matched each parenthesized group in the regular expression. Destructuring assignment allows you to pull the parts out of this array easily, ignoring the full match if it is not needed.

var url = "https://developer.mozilla.org/en-US/Web/JavaScript";

var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
var [, protocol, fullhost, fullpath] = parsedURL;

console.log(protocol); // logs "https:"

Object destructuring

Simple example

var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true 

// Assign new variable names
var {p: foo, q: bar} = o;

console.log(foo); // 42
console.log(bar); // true  

Assignment without declaration

Destructuring assignment can be made without a declaration in the assignment statement.

var a, b;

({a, b} = {a:1, b:2});

The ( .. ) around the assignment statement is required syntax when using object literal destructuring assignment without a declaration.

Function argument defaults

ES5 version

function drawES5Chart(options) {
  options = options === undefined ? {} : options;
  var size = options.size === undefined ? 'big' : options.size;
  var cords = options.cords === undefined ? { x: 0, y: 0 } : options.cords;
  var radius = options.radius === undefined ? 25 : options.radius;
  console.log(size, cords, radius);
  // now finally do some chart drawing
}

drawES5Chart({
  cords: { x: 18, y: 30 },
  radius: 30
});

ES6 version

function drawES6Chart({size = 'big', cords = { x: 0, y: 0 }, radius = 25} = {}) 
{
  console.log(size, cords, radius);
  // do some chart drawing
}

drawES6Chart({
  cords: { x: 18, y: 30 },
  radius: 30
});

In Firefox, default values for destructuring assignments are not yet implemented: var { x = 3 } = {} and var [foo = "bar"] = []. See for destructured default values in functions.

Module (non-ES6) loading

Destructuring can help to load specific subsets of a non-ES6 module like here in the Add-on SDK:

const { Loader, main } = require('toolkit/loader');

Nested object and array destructuring

var metadata = {
    title: "Scratchpad",
    translations: [
       {
        locale: "de",
        localization_tags: [ ],
        last_edit: "2014-04-14T08:43:37",
        url: "/de/docs/Tools/Scratchpad",
        title: "JavaScript-Umgebung"
       }
    ],
    url: "/en-US/docs/Tools/Scratchpad"
};

var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;

console.log(englishTitle); // "Scratchpad"
console.log(localeTitle);  // "JavaScript-Umgebung"

For of iteration and destructuring

var people = [
  {
    name: "Mike Smith",
    family: {
      mother: "Jane Smith",
      father: "Harry Smith",
      sister: "Samantha Smith"
    },
    age: 35
  },
  {
    name: "Tom Jones",
    family: {
      mother: "Norah Jones",
      father: "Richard Jones",
      brother: "Howard Jones"
    },
    age: 25
  }
];

for (var {name: n, family: { father: f } } of people) {
  console.log("Name: " + n + ", Father: " + f);
}

// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"

Pulling fields from objects passed as function parameter

function userId({id}) {
  return id;
}

function whois({displayName: displayName, fullName: {firstName: name){
  console.log(displayName + " is " + name);
}

var user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"

This pulls the id, displayName and firstName from the user object and prints them.

Computed object property names and destructuring

Computed property names, like on object literals, can be used with destructuring.

let key = "z";
let { [key]: foo } = { z: "bar" };

console.log(foo); // "bar"

Firefox-specific notes


  Created by Mozilla Contributors, license: CC-BY-SA 2.5