OdeToCode IC Logo

Features Of ES6 Part 6: Destructuring

Thursday, September 11, 2014

To destructure an object is to dismantle or tear apart an object.

In ES6, a destructuring assignment allows us to tear apart an array or object into individual pieces that we can assign to variables. The square brackets [ and ] are used to destructure an array, while { and } will destructure an object.

The following code will destructure an array so that x contains 22 and y contains 44.

let values = [22, 44];
let [x, y] = values;

expect(x).toBe(22);
expect(y).toBe(44);

You can think of [ and ] in the first line of code as the symbols used to construct an array. The [ and ] on the second line of code tear apart the array and declare two variables to hold the pieces.

Destructuring objects follows the same pattern, but will use { and }.

var person = { firstName: "Scott", lastName: "Allen" };
var {firstName, lastName} = person;

expect(firstName).toBe("Scott");
expect(lastName).toBe("Allen");

You do not need to use let or var with destructuring to create new variables, you can also destructure into existing variables.

let x = 10, y = 20;

// swap!!
[x,y] = [y,x];

expect(x).toBe(20);
expect(y).toBe(10);

You can also destructure arrays and objects returned from a function call.

var doWork = function() {
    return [1, 3, 2];
};

let [, x, y, z] = doWork();

expect(x).toBe(3);
expect(y).toBe(2);
expect(z).toBeUndefined();

Note a couple special properties in the destructuring of doWork’s result. First, the opening comma will skip the first array element, and you can use additional commas anywhere to skip additional elements. Secondly, if there are not enough array elements to satisfy all the variables required by the destructuring, the extra variables will receive the value undefined.

You can also destructure in a function parameter list.

let doWork = function({firstName, lastName, role="developer"}) {
    return role + " " + firstName + " " + lastName;
};

let person = {firstName: "Scott", lastName: "Allen"};
let result = doWork(person);

expect(result).toBe("developer Scott Allen");

The above example also uses a default parameter value to assign “developer” to the role parameter in case the incoming object does not have a role property (otherwise, role would receive the value undefined). Default parameters are not restricted to function declarations when using destructuring.

let address = { state:"Maryland" };
let { state="New York", country="USA"} = address;

expect(state).toBe("Maryland");
expect(country).toBe("USA");

Rest parameters can also capture the remaining elements of an array.

let odds = [1,3,5,7,9];
let [first, second, ...rest] = odds;

expect(first).toBe(1);
expect(second).toBe(3);
expect(rest).toEqual([5,7,9]);

Destructuring can also drill into complex objects, even objects with collections inside.

let employee = {
    firstName: "Scott",
    address: {
        state: "Maryland",
        country: "USA"
    },
    favoriteNumbers: [45,55,32,13]
};

let { firstName, address: {state}, favoriteNumbers: [,second]} = employee;

expect(firstName).toBe("Scott");
expect(state).toBe("Maryland");
expect(second).toBe(55);
The Significance of Destructuring

One area where destructuring will lead to more maintainable code is in the use of configuration objects, like the configuration objects you typically pass to HTTP communication methods like jQuery’s ajax method. Finding the available options and their defaults is often difficult when using such a method, and maintaining the options and defaults can be tricky as an author. With destructuring, configuration options and defaults become more explicit.

let httpPost = function(
        url, {
        cache = true,
        contentType = "application/json",
        timeout = 2500,
        headers = {},
        // ...
    }) {
        // ...
};

We’ll also see other uses for destructuring as we move through additional features of ES6, like modules.

Want more? Watch JavaScript Fundamentals for ES6 on Pluralsight!