8

So basic desctucturing is fine, {a, b} = obj transpiles to a = obj.a; b = obj.b.

My question is around a bit of an odd syntax that I accidentally ran across and I'm wondering if someone can point me at spec since I can't find it:

({a, b} = obj).c

That does the two a, b assignments and then returns obj.c. It's actually quite useful to me for a byte stream decoder, as I can write:

let width = ({bytes} = intDecode(bytes)).number;

My issue is that I haven't seen this syntax anywhere and don't want to rely on something that is either incorrectly implemented or in proposal stage.

  • It's the same as `(obj = intDecode(bytes)).number; bytes = obj.bytes` (maybe except for evaluation order) - same odd syntax in ES5. Make sure though that `bytes` is declared somewhere. – Bergi Sep 03 '15 at 12:27

2 Answers2

2

There is nothing special in Destructuring Assignment: it's evaluated as any other Assignment with = operator.

So it returns rval.

Which means you can rely on your syntax.

Some details:

The Destructuring Part is evaluated in the 6[1]:

Let status be the result of performing DestructuringAssignmentEvaluation of assignmentPattern using rval as the argument.

and after this item the assignment evaluation happens as usually, like in the a = b = 42; case.

References:

zerkms
  • 249,484
  • 69
  • 436
  • 539
  • It's arguable what the `rval` actually is here, however. 12.4.4(1.a) -- `Let rref be the result of evaluating AssignmentExpression.` -- I'd argue that in `({a} = obj)`, `rval === obj.a`, _not_ `obj` –  Sep 03 '15 at 08:15
  • @zyklus it's not, `rval` is the value of the right operand of the `=` operator. `4. Let rval be GetValue(rref).` – zerkms Sep 03 '15 at 08:16
  • 1
    In `({a} = obj)` expression `rval` is the `obj`, as per specification. `obj.a` is looked up during the destructuring assignment evaluation which has `obj` passed as a parameter. – zerkms Sep 03 '15 at 08:17
  • Okay, I can accept that -- thanks. My objection was around confusion as to what would actually be going on here during a transpilation process, which would be `(a = obj.a)` -- but you're right, that's part of the desctruring –  Sep 03 '15 at 08:19
1

Yes, it is expected to work like this (see @zerkms' answer for details). That you haven't seen the syntax anywhere is because it's not exactly good practice to access properties on the result of an assignment expression, as it makes the code quite unreadable. Whether you assign to a normal variable or a destructuring expression doesn't make much difference here.

However, you could quite easily transform the code into a reasonable destructuring assignment:

let {bytes, number:width} = intDecode(bytes);

or actually, more closely to your original code:

let width;
({bytes, number:width} = intDecode(bytes));
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • @Felix Kling: are those parentheses just to look more like OP's original code or something else? – zerkms Sep 04 '15 at 02:51
  • 2
    @zerkms: `{...} = foo` is a syntax error because the `{}` are interpreted as block. Parentheses are need to enforce them being parsed as pattern. – Felix Kling Sep 04 '15 at 02:56
  • @FelixKling: Thanks. I always feel something is not right when I start a destructuring assignment statement with a `{`, but attribute that to ES6 not the syntax error that it is since long… I wonder how many people it trips up daily. – Bergi Sep 04 '15 at 10:13