.

Tags:

In a programming language, destructuring assignment denotes the use of patterns to extract parts of an object. If we refer to Common LISP, destructuring assignment binds a set of variables to a corresponding set of values, where normally bind a value to a single variable. For the next-generation ECMAScript 6, destructuring feature is slated to be an important addition to the assignment expression.

Python developers might be already familiar with the concept of sequence unpacking. CoffeeScript also already has the syntax for destructuring. SpiderMonkey, the JavaScript engine in Firefox, has been supporting destructuring assignment for a while. The latest ECMAScript 6 defines the grammar for destructuring assignment in Section 11.13.1. There are two different forms: array pattern and object pattern.

Array Pattern

Variables can be initialized in one go. The following two lines have the same effect, the first one is employing an array pattern.

var [m, d, y] = [3, 14, 1977];
var m = 3, d = 14, y = 1977;

Swapping two variables is rather trivial, this one works just as expected. Internally, it does the sequence as if there is a temporary variable temp and the usual value exchange.

x = 3; y = 4; [x, y] = [y, x]
temp = [y, x]; x = temp[0]; y = temp[1];

Another typical use of array restructuring is for a function which has multiple return values. We don’t need to wrap it in an object anymore. Also, there is no need to accept all elements in the array.

function now() { return [2, 6, 2013, 8, 0]; }
var [m, d] = now(); // m = 2, d = 6
var [,,year] = now(); // year = 2013

With the syntax visualization feature of Esprima, it is rather easy to illustrate the syntax tree of an array pattern. The following figure shows an example thereof. Compared to a vanilla assignment or variable declarator, the obvious different here is that we have an array pattern instead of a plain identifier.

Array pattern syntax tree

Object Pattern

This pattern is very similar, except it works by matching object properties instead of array indices. Thus, we can easily pick the ones we are interested in while ignoring the rest. A similar example as before, e.g. when processing the return value of a function:

function today() { return { d: 6, m: 2, y: 2013 }; }
var { m: month, y: year } = today(); // month = 2, year = 2013

Of course, instead of a pattern, nothing stops you from assigning a holder object before accessing each property. However, the lack of such extra object makes the code looks cleaner (or sweeter, since destructuring is supposed to be a syntactic sugar), in particular when it is part of a loop.

books.forEach(function ({ title: title, author: author }) { console.log(title, author) }; )

In the above construct, every element in that books array may contain a lengthy information about that particular book. Since we just want some properties, it is possible to extract them directly via the object pattern.

It gets even more interesting once we combine with array comprehension. For example, the following line is exactly the same as the above snippet:

[console.log(t,a) for ({title: t, author: a} of books)];

How do you plan to (ab)use array and object pattern?

  • http://liamnewmarch.co.uk/ Liam Newmarch

    I apologise if I’m wrong, but shouldn’t the Object Pattern example be written `{ month: m, year: y}` instead of `{ m: month, y: year }`? It seems strange that the assignment would come before the variable name.

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Because it’s not a assignment, it’s a pattern matching. Imagine if you have to match an object with nested properties, e.g `{ x: { y: 4, z: 5 } }`.

    • Daniel

      You can read `{m: month, y: year}` like “m as month, y as year” and that will make things a lot clearer.

  • rwaldron

    At the January 2013 TC39 Meeting[0], we came to consensus on flipping comprehensions so that they appear in the order that developers are (most likely) more familiar with, which means:


    [ console.log(t,a) for ({title: t, author: a} of books) ];

    Should be flipped to this:


    [ for ({title: t, author: a} of books) console.log(t,a) ];

    [0] https://github.com/rwldrn/tc39-notes/blob/master/es6/2013-01/jan-31.md#comprehensionsgenerator-syntax

    • http://ariya.ofilabs.com/ Ariya Hidayat

      I like the new construct :) Thanks for the notice!

      • rwaldron

        I agree, it’s much nicer this way :)

  • BrianFrichette

    CoffeeScript’s current implementation (for those who want to use this now): http://coffeescript.org/#destructuring

    • http://ariya.ofilabs.com/ Ariya Hidayat

      Already linked in the blog post. For completeness, one can also use Traceur or TypeScript.

      • BrianFrichette

        Ooops. Sorry :)

        • http://ariya.ofilabs.com/ Ariya Hidayat

          No worries :)

  • Jeff Schwartz

    One of the best features to come out of the es6 spec. A boon to every developer!

  • Matthew Kastor

    Good article. :D This will be good stuff once it’s available by default.