6

Why did ES6 decide that left-side assignment made more sense or was more useful for destructured assignments? Just on first look, it seems to make code more error prone, now that assignment can happen on both sides, depending on situation.

let obj = { first: 'Jane', last: 'Doe' };
let { first: f, last: l } = obj;
// f = 'Jane'
// l = 'Doe'

f and l are both seemingly being defined on the left, using values from a combination of the var names on the left and values of those vars from the right.

Given that the rationale for this sytax is the keep it the same as object declaration syntax, why would ECMA not instead have used:

let { f: first, l: last } = obj;
BrianFreud
  • 7,094
  • 6
  • 33
  • 50
  • 5
    "now that assignment can happen on both sides" The variables you assign to is still on the left side, the data you assign to those variables still on the right, no? – tkausl Nov 19 '16 at 22:10
  • 2
    can you show some code you think is confusing to you? – Jaromanda X Nov 19 '16 at 22:10
  • 2
    you mean why in `const {foo: bar} = a` the new varable is `bar` not `foo`? – Kos Nov 19 '16 at 22:11
  • @tkausi no; I'll add an example of array destructuring. – BrianFreud Nov 19 '16 at 22:12
  • And what's your alternative? – melpomene Nov 19 '16 at 22:23
  • Just off the top of my head, something like let { f, l } = obj {first, last}; – BrianFreud Nov 19 '16 at 22:24
  • OK, but that's not destructuring then. – melpomene Nov 19 '16 at 22:25
  • Compare obj = { first: 'Jane', last: 'Doe' } with { first: f, last: l } = obj. Even there, the order is reversed. – BrianFreud Nov 19 '16 at 22:27
  • 1
    @BrianFreud I don't know how you expect your alternative to work - objects are _not_ ordered so doing `let {f, l} = obj` is going to give you RANDOM properties from the object. So, if you want to have specific properties, you'd need to lable them...which leaves you with `let {first: f, last: l}`. The thing you find "confusing" and "error prone" yet it's exactly the opposite. – VLAZ Nov 19 '16 at 22:28
  • @BrianFreud `Compare obj = { first: 'Jane', last: 'Doe' } with { first: f, last: l } = obj. Even there, the order is reversed.` sure, because they have a very different meaning, however, both of them assign the right side to the left side. – tkausl Nov 19 '16 at 22:29
  • 1
    I don't understand what you mean by "reversed". Assignment goes from right (source value) to left (target). – melpomene Nov 19 '16 at 22:29
  • @melpomene see Kos' comment above. In the destructured syntax, assignment goes from left (value) to right (target var) – BrianFreud Nov 19 '16 at 22:31
  • No, `first` is not a value. It's part of the structure of the object we're in. It plays the same role as `{`, `,` or `}`. – melpomene Nov 19 '16 at 22:32
  • @vlaz, forget that I used {}; I intended something like a tuple's collection, not literal object notation. Something like let ( f, l ) = obj (first, last) if you like, where first and last are getting their values from obj. – BrianFreud Nov 19 '16 at 22:33
  • JavaScript objects are like records. Records are tuples where the values are identified by name, not position (`first: ..., last: ...`). This seems all consistent to me. Your syntax (object slicing) wouldn't work for function parameters, where you only specify the "left" side. – melpomene Nov 19 '16 at 22:36
  • @BrianFreud are you confused at what left and right are? Because `let {first: f, last: l} = obj` _is_ left assignment. Left - left side of the equals, right - right side of the equals. The assignment is clearly on the left side. The fact that `f` is "on the right" of the identifier `first` does not make it "right assignment". – VLAZ Nov 19 '16 at 22:38
  • Destructuring syntax designates *a path* to nested properties. See [this answer for details](http://stackoverflow.com/a/38667613/3731501). If you have problems with interpreting this syntax, take some time to become comfortable with it. It's like complaining that spread and rest operators behave differently. They are different things - so object literals and destructuring are. – Estus Flask Nov 19 '16 at 22:41
  • @vlaz, let {first: f, last: l} = obj contains three assignments. melpomene, you can define both a left and right (default value) for function params. Sticking with the existing syntax, though, why would you not want { f: first, l: last } as the order? Estus, that doesn't really have much to do, imho, with the chosen order of "first: f" over "f: first", especially when the rationale for the syntax is "to make it the same syntax as object declaration"... when in reality, it looks the same but reverses the order. – BrianFreud Nov 19 '16 at 23:02
  • `et {first: f, last: l} = obj contains three assignments` no, it doesn't. It's clearly _two_ - the `f` and the `l`. – VLAZ Nov 19 '16 at 23:08
  • I completely agree with @BrianFreud's original question. `let { f: first, l: last } = obj;` makes so much more sense cognitively. The first thing you recognize is a familiar pattern of object property assignment `{f: first}` which in your mind has the key "f" get the value (contained by) "first". When you scan the (ES6 correct) code `let {first:f, last:l} = obj` your mind sees the "first" and "last" as keys. You are much more likely to (mistakenly) assume that "first" is the var name, not "f". I, like the OP, would love to better understand the REASON it was decided to be that way. – Tom Auger May 24 '19 at 03:26

1 Answers1

9

Because it is supposed to keep the object literal syntax: the property name comes before the colon. The syntax is supposed to nest, and that wouldn't work properly if the target was on the left side:

let {propName: [arrayElement, ...moreElements], otherName: {nestedProp: targetName}} = obj;

In your approach, it would be

let {[arrayElement, ...moreElements]: propName, {targetName = nestedProp}: otherName} = obj;

where the colon doesn't make any sense.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    Good point, but one could argue that the colon doesn't make any sense regardless and including it in the destructuring synrax is the source of the confusion to begin with... – Hamid Sadeghian Nov 11 '18 at 10:52
  • Right - they could have done away with that colon in favour of some other token. This is just very confusing - it looks like you're assigning to a property `first` the value (contained by) `obj.f`, which is in fact the opposite of what's occuring. `{first -> f, last -> l} = obj` might have been a better approach – Tom Auger May 24 '19 at 03:29
  • @TomAuger The operator really doesn't matter. `:` in JavaScript is what `->` is in PHP or Scala. – Bergi May 24 '19 at 10:11
  • 2
    @Bergi I wasn't making a syntactic point, but a cognitive one. When you're designing a new language construct, with a new kind of operator, you have the opportunity to decide what token expresses the function of the operator. The decision to use ":" to alias `oldkey : newkey` does not exactly correspond to the existing paradigm of `key : value`. – Tom Auger May 27 '19 at 17:55
  • @TomAuger It's not `oldkey : newkey` but rather `key: target`, which matches `key: value` just fine. – Bergi May 27 '19 at 18:21