Thomas R Alexander

Manager, Developer, and professional problem solver

Why Destructuring is a Terrible Idea in ES6

Destructuring is a concept introduced in ES6 that allows developers to destructure objects into variables without explicitly setting a variable to the object key/val. Confused? Yeah you’ll be even more confused as you start reading.

What is happening in this statement?

Is it obvious to you that f and l are new variables created from the values named first and last in the “obj” object?

I bet not.

How about this one?

Is it obvious to you that two new variables are being created, x= ‘a’ and y = ‘b’?

I didn’t think so either.

It gets worse.

What the bleep is going on here? Would you guess that we’re only creating a variable x (set to the value of x) and ignoring y?

It gets even uglier.

Go ahead. Tell me seriously what’s going on here at first glance.

It gets even worse.

So you can call a property of a string value too? That’s fun and clear, isn’t it?

The syntax is absolutely confusing and is going to introduce some ugly, ugly code and bugs. It *can* be useful and enable you to write some pretty clean code, but its potential for misuse outweighs its benefit.

Tread lightly and be sure to not misuse its power. These are pretty contrived examples for the purposes of demonstration, but I wanted to show that just because it can shorten the number of lines in your code doesn’t mean that it enhances readability. Readability is much more important than breviloquence in code.

40 thoughts on “Why Destructuring is a Terrible Idea in ES6

  • Hunter Cassidy
    June 11, 2015 at 10:40 am

    While I agree that the object destructing syntax can be a tad confusing, the array syntax is pretty much just a copy of common, pattern matching syntax.

  • Barney
    June 12, 2015 at 12:44 pm

    I’m with you on renaming during destructuring – it’s almost too terse to make sense, plus order is inversed, which means the local reference is hard to find at a glance.

    But if you can say the same about a lot of features in Javascript. Array literals?! They’re a disaster waiting to happen!

    [] + [] === ”

    The above is something you’d never do. You wouldn’t write it, and you wouldn’t have any other expectations of it. It gives some indication of how type coercion works, so it’s somewhat useful as a demonstration of that particular feature, but without any explanation or intent, asking people who are new to this functionality if they’re confused is going to get you a resounding “yes” – because it’s a straw man.

    In the situations where you’re assigning object properties to local variables len, t and f, it’s not clear what purpose is being served (presumably none). But if we ditch the renaming aspect, things get a bit clearer:

    let { length } = ‘Thomas Alexander’

    …this gets us closer to understanding how destructuring might be useful as a way of extracting properties from objects as local references. That code above is pretty much the same as

    let length = ‘Thomas Alexander’.length

    …But it saved us some bytes. It gets far more useful if you want to grab several references from an object in one sweep, especially in function signatures. Here’s a dumb function for getting peoples’ full names in ES5:

    function full( person ){
    return person.first + ‘ ‘ + person.name
    }

    And in ES6:

    const full = ( { first, last } ) =>
    first + ‘ ‘ + last

    • teeohhem
      June 12, 2015 at 12:56 pm

      Certainly. You’re right, there’s a lot of potential for ugly in the language.

      Can we both agree that it’s ugly and hinders readability at least? 🙂 Sure it saves some bytes, but clarity goes a long way.

      • Paul
        June 12, 2015 at 2:50 pm

        Destructuring is not a new concept and has been successfully implemented in other languages like Python, Clojure, Perl, etc. It is simply another tool to boil code down to its intent without extra fluff. New syntax can be off-putting at first, but I don’t think the sky is falling.

        • teeohhem
          June 12, 2015 at 7:12 pm

          It’s a bit late to the game in JavaScript as a standard, don’t you think? Now we have three different ways of defining variables in Javascript. WEEEE!

          • James
            October 14, 2015 at 8:26 am

            I have to agree with you there. Further to that I feel strongly that ES6 should of been focussed primarily around simplifying the language and ironing out the ‘bad parts’ instead of borrowing concepts from other languages to appease people who are too stubborn to part with their classical OO languages and tools.

      • Tyler Eich
        June 12, 2015 at 6:08 pm

        Destructuring hinders readability the same way ternary operators, || short-circuiting, and !! boolean casting hinder readability. They’re powerful shortcuts with potential for abuse, but I can’t imaging any JavaScript dev advocating their removal. And with experience, parsing the shorthand becomes second-nature.

        Object destructuring is not the problem. Developers who write spaghetti code will do so regardless of the available shorthands.

        • teeohhem
          June 12, 2015 at 7:10 pm

          Very good point. It’s so odd to have comments that aren’t overly negative and berating, so thank you!

          I think the concept is cool, but I find it hard to read. It’s a syntax that is so inconsistent with traditional JavaScript that it just sticks out like a sore thumb, ya know? I don’t doubt its usefulness, however!

        • Havvy
          June 12, 2015 at 7:34 pm

          I’d actually rather not have the ternary operator but have if be an expression itself. Though since that’s not the case, I do use the ternary operator in its place.

          Short circuiting is fine.

          I don’t see a reason to use !! instead of Boolean().

          Object destructuring is fine. I could read each of those examples perfectly. And it’s not calling a function, it’s grabbing a property off of a string. Which is /weird/ but entirely possible. I’d probably use “abc”.length in that case.

          • teeohhem
            June 12, 2015 at 7:52 pm

            Yeah it was a miswording on my part. I’ll update the post. Thanks for the comment!

  • Serge
    June 12, 2015 at 12:52 pm

    “I recommend skipping over this in ES6.”

    ಠ_ಠ really?

    • teeohhem
      June 12, 2015 at 12:57 pm

      I believe its potential for bad outweighs any benefits. I also think it makes the code more difficult to read.

  • Roy Tinker
    June 12, 2015 at 1:29 pm

    let obj = { t: [{ first: “Tom”, last: “Alexander” }, {}], a: true };
    let { a: [{t: f}] } = obj;

    I don’t think that will evaluate without throwing an exception. It looks like you’re attempting to treat obj.a as an array of objects, when it’s actually a boolean.

  • Jarrod
    June 12, 2015 at 1:32 pm

    A lot of language features look uncomfortable at first. Long form, deep destructuring may be ugly but the functionality exists for consistency. Just because it exists doesn’t mean you need to use it and you can rely on linters to enforce sane styling.

    Destructuring combined with object shorthand makes the syntax let {x} = someObject palatable and once the idiom becomes recognizable then deciphering its meaning becomes second nature (akin to IIFEs or nearly any pattern in JS).

  • Roy Tinker
    June 12, 2015 at 2:12 pm

    Many debates in programming come down to the classic “Directing vs. enabling” dichotomy. It sounds like you favor a Directing attitude with regard to destructuring.

    Martin Fowler has an excellent bliki entry on the topic: http://martinfowler.com/bliki/SoftwareDevelopmentAttitude.html

    I’m firmly in the “enabling” camp here:I think destructuring is a great feature because of the open-ended expressive power it provides, despite the likelihood that some will abuse it to create hard-to-read incantations.

  • Rich Harris
    June 12, 2015 at 2:22 pm

    Used correctly, destructuring allows you write beautifully elegant code. (As a community we’re still figuring out what the limits of ‘correctly’ are – this article does indeed contain some examples of destructuring that are less readable than the ES5 equivalents, and you’re right to point out how bad they are.) It’s like arrow functions – odd at first, but your fingers will thank you for persevering.

    Re ‘I recommend skipping over this in ES6’ – other people (me!) will be (and are) using destructuring. Choosing not to use it in your own code is one thing, but explicitly rejecting it means that everyone else’s code will become unreadable to you!

    • teeohhem
      June 12, 2015 at 7:15 pm

      THanks for the feedback, Rich!

  • Kyle Simpson
    June 12, 2015 at 2:26 pm

    I think you’ve really missed the entire point of destructuring, which leads to your conclusions about its readability.

    What you’re missing is the context of what it’s replacing. When you consider the before/after of many examples, the ES6 destructuring is way, way more readable. But not “readable” in the commonly misappropriated sense, like “can i glance at it and understand immediately what it means”. Rather, in the “does it have logical rules and consistency that I can learn and then be able to understand its various variations”.

    Let me illustrate:

    ES5:

    function foo(x) {
    return { x: x, y: x * 2, z: x + 100, w: [x + 1, x + 2, x + 3, x + 4] };
    }

    var tmp = foo(10),
    a = tmp.a !== undefined ? tmp.a : 0,
    x = tmp.x !== undefined ? tmp.x : 8,
    y = tmp.y,
    z = tmp.z !== undefined ? tmp.z : 1000,
    w = tmp.w !== undefined ? tmp.w : [],
    w0 = w[0] !== undefined ? w[0] : 5,
    w1 = w[1] !== undefined ? w[1] : 500,
    w2 = w[2] !== undefined ? w[2] : 5000,
    wRest = w.slice(2);

    ————

    ES6:

    function foo(x) {
    return { x, y: x * 2, z: x + 100, w: [x + 1, x + 2] };
    }

    var {
    a = 0,
    x = 8,
    y,
    z = 1000,
    w: [
    w0 = 5,
    w1 = 500,
    w2 = 5000,
    …wRest
    ]
    } = foo(10);

    ————

    As with most of the new syntax additions in ES6, the point is about taking the older idioms that are verbose and confusing and expressing them in a sensible and readable (aka, “learnable”) way.

    Can they be abused? Of course they can. But power used correctly in the learned hand produces something much better in ES6 than they ever could in ES5. That’s one of the most important narratives about ES6.

    • teeohhem
      June 12, 2015 at 7:15 pm

      Well you’ve overcomplicated your ES5 example. It’s better written as:

      var tmp = foo(10),
      a = tmp.a || 0,
      x = tmp.x || 8,
      y = tmp.y,
      z = tmp.z || 1000,
      w = tmp.w || [],
      w0 = w[0] || 5,
      w1 = w[1] || 500,
      w2 = w[2] || 5000,
      wRest = w.slice(2);

      After seeing that, I don’t see how destructing makes that cleaner. It’s very odd to me that it’s becoming a standard feature as part of the language.

      • Tyler Eich
        June 12, 2015 at 7:42 pm

        Short-circuiting is usually adequate, but it breaks down when your object contains other falsey values (false, "", 0, null, NaN). Default values are only applied when tested undefined.

        MDN has a good example where destructuring arguably helps readability, namely functions that take an object of options:

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


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

        https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

        • teeohhem
          June 12, 2015 at 7:54 pm

          Smaller isn’t always better. I can read the ES5 option much easier (and yes, I’d use short-circuiting and update my API accordingly to make it cleaner). The ES6 function using destructuring hides a lot of things behind the scenes and no longer makes your code straight-forward (imo).

      • Nate Cavanaugh
        December 3, 2015 at 4:50 pm

        I generally agree with you about the destructuring syntax, in that it’s insanely hard to read the more it’s used.
        However, just a minor nitpick, the issue with your simplified form of Kyle’s example is that there’s a difference between a falsey value like 0 and undefined.
        All of those numbers may want to accept 0 as valid.

    • Nate Cavanaugh
      December 3, 2015 at 4:59 pm

      Kyle, the one thing I would disagree with you on is about the readability statement.
      The “can I understand it at a glance” is not a misappropriation of the term, but one of the ways in which it’s defined (and when it comes to code, IMHO, I think it’s one of the most important factors).
      I think your quote of “does it have logical rules and consistency that I can learn and then be able to understand its various variations” is somewhat tautological, because we’re talking about a programming language. Of course it has logical rules and consistency that you can learn.
      Assembly is readable by that measure.

      But that’s not the issue here. And the issue isn’t even that it’s brand new syntax.
      The main issue is that even after your familiar with it, there’s a ton of potential abuse in there for the sake of one immediate developer’s convenience.
      It’s like single letter variables. Sure they’re allowed, and even totally acceptable in some cases, but only really bad or inconsiderate programmers ship code that use them liberally.

      In general, though, I’m not against the syntax, and glad it’s available for those cases where readability isn’t improved by verbosity.
      But I dread opening up someone’s code and finding some of the examples above 🙂

  • Jeremy Fairbank
    June 12, 2015 at 3:39 pm

    While I agree that deeply nested destructuring is unreadable, I believe that by-and-large this is a very readable syntax. Saying that the potential for misuse negates the benefits is a little too much. I’ve read through plenty of gross misuse of non-ES6 JS syntax too. Does that mean we eschew the language entirely?

    I understand that readability is subjective, so this may not be your cup of tea, and that’s completely fine. I believe this is a common pattern that most people are used to in other languages and will adopt. I find the conciseness and readability to be a great boon to my code.

  • chris-l
    June 12, 2015 at 4:51 pm

    Perhaps is my perl background, but I don’t see destructuring as a bad thing.

    Of course, I agree it can be misused to create hard to read code.

    While some of your examples are indeed hard to read, this particular example:
    let [x, y] = [‘a’, ‘b’];
    Well IMHO, I think that one is really obvious.

    (Obvious IF the person reading it knows what destructuring is.)

    • teeohhem
      June 12, 2015 at 7:11 pm

      Thanks for the feedback, Chris!

  • Martin Genev
    June 12, 2015 at 5:26 pm

    sure if you try hard you can make a confusing contrived example, but the truth is this is quite convenient and i’ve been using it for 2 years without ever having been confused.

    • teeohhem
      June 12, 2015 at 7:11 pm

      Congratulations. What’s your address? I’d love to send you a cookie.

  • Tom
    June 12, 2015 at 6:20 pm

    I’ve had lots of great productivity with my colleagues using destructuring syntax.

    We follow the idea that if it’s looking complicated — you’re using it wrong.

    Like any new syntax, it takes time to adjust for reading it.

    I think your contrived examples give a poor representation of the feature.

    We have a common use case


    let { user, item, page } = this.state;
    let { id, userId } = item;
    // go have fun

    It’s trivially easy to read.

    • teeohhem
      June 12, 2015 at 7:06 pm

      I disagree. Mixed with traditional JS, it sticks out like a sore thumb. I think at a glance, it’s an eyesore.

      • Cyril Sobierajewicz
        June 13, 2015 at 7:35 am

        Traditional cooking as you call it is fading away thanks to ES2015. Destructuring can feel a bit out of place taken in isolation but it blends very well with other new features, mainly shorthand property assignment, default arguments and the rest operator.
        Besides that, easiness lies in the eye of the beholder. The easiness of something is a subjective notion that rest entirely on your passed learnings and so doesn’t hold too much of intrinsic value.

        • Cyril Sobierajewicz
          June 13, 2015 at 7:37 am

          *JS. Obviously I didn’t want to talk about cooking.

  • Shamasis Bhattacharya
    June 13, 2015 at 4:22 am

    if we were to make JavaScript adhere to the needs of only those with limited readability skills, we would then had not needed any new revisions of JS post ES 4. We would also have long and winding codebases that do allow readability at a micro level but prevent anyone from skimming code to get the bigger picture. We would also spend hours writing the code instead of using our mind to create any genius algorithm.

    If readability is such a problem for some, IDEs can be equipped with AST parsers that demystify such lines of code.

  • Vince
    June 13, 2015 at 4:38 am

    But think of the transpiler writers!!!

  • Will
    June 13, 2015 at 5:07 am

    More than anything else your examples have demonstrated that destructuring a complicated structure is complicated, and doing it in one line is hard to read.

    It wouldn’t matter whether you used ES6 destructuring assignment or ES5 statements to do it, in either case you’d break it up to simplify it.

    Also, destructuring is already decades old (see Lisp, Haskell or Prolog, and more recently Ruby), this is just the first time it’s appearing in JavaScript.

  • Gerald
    June 13, 2015 at 7:48 am

    I use destructuring & pattern matching in Clojure and Elixir where it is taken to the limit and, believe me, it certainly enhances the language and coding experience. This is a grate feature to have in ES6.

  • It’s Clean Jim, But Not As We Know It | Zombie Code Kill
    June 13, 2015 at 8:58 am

    […] It kicked off a little bit on Twitter earlier today over readability and clean code following the article Why Destructuring Is A Terrible Idea. […]

  • Jos de Jong
    June 13, 2015 at 9:25 am

    Is the destructuring syntax readable? Yes! I love it!

    I totally agree with you that you shouldn’t overuse it. There must be a very good reason to use it for mapping object properties to variables with a different name, or to use nested destructuring.

    It’s not really fair that you mostly show these advanced usages of destructuring in your article instead of the basic syntax of let {x, y, z} = point3d;. You will hardly need the advanced usages in practice, whilst the regular use case gives us a beautiful way to write your intent in a compact, readable way.

    MDN shows a lot of beautiful, simple, more realistic usage examples for destructuring, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

  • Joe Zim
    June 14, 2015 at 7:56 pm

    I can see this being discussed in a new edition of JavaScript: The Good Parts. I think the renaming syntax is backward from what you would expect, and doing something advanced with it is ridiculous, but the basic use case is awesome… so yea. Just tread with care.

  • Phil
    December 13, 2015 at 3:29 pm

    This confused me until I realised it’s just like Linq.

    let { x: x } = { x: 2, y: 3 };

    var x = from x in { x: 2, y: 3 }, select x;

Leave a Reply

Your email address will not be published. Required fields are marked *.

*
*
You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">


4 + 2 =