1

This code works:

let foo;

(foo) = 'bar';

console.log(foo);

And that makes me believe that any expression works as a left-hand side in assignment, however, this code doesn't work:

let foo1 = "bar";
let foo2;
let foo3;
(foo1 && foo2 && foo3) = "foobar"; // The left-hand side evaluates to undefined which can't be assigned

console.log(foo1, foo2, foo3);

What makes a left-hand side valid in an assignment, why it can't always be an expression?

Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • 6
    Nitpick and unrelated to the question: _"And that makes me believe that any expression works as a left-hand side in assignment"_ 2, 4, 6, 8 are even numbers. This makes me believe that all numbers are even numbers. This logic doesn't work. – Thomas Sablik Feb 18 '21 at 08:53
  • @ThomasSablik then let me rephrase it: which particularity of the first case makes it work, and why? – Guerric P Feb 18 '21 at 08:55
  • Yes, the question is completely clear for me. I also upvoted it because I think it's a good question. I said it's a nitpick and unrelated. But you should make such assumptions. That's can cause errors – Thomas Sablik Feb 18 '21 at 08:57
  • 3
    _“// The left-hand side should return foo2”_ - it doesn’t return _a variable_, it returns the _value_ of the logical expression. – CBroe Feb 18 '21 at 09:00
  • Expression works on the left side, `(foo1 && foo2 && foo3)` returns `undefined` which makes the left-hand side operator invalid for assignment. – Teemu Feb 18 '21 at 09:01
  • Then why the first case is not equivalent to `undefined = 'bar'` which should be invalid too? – Guerric P Feb 18 '21 at 09:05
  • "*that makes me believe that any expression works as a left-hand side in assignment*" this is trivial to disprove `4 = "bar"` doesn't work. Ergo, "any expression" is false. – VLAZ Feb 18 '21 at 09:05
  • Relevant: [What's a valid left-hand-side expression in JavaScript grammar?](https://stackoverflow.com/q/3709866) – VLAZ Feb 18 '21 at 09:14
  • Does that mean that an expression which contains a single variable name evaluates to a reference, while a more complex expression evaluates to a value? – Guerric P Feb 18 '21 at 09:16
  • @GuerricP I guess so. The grouping operator is to change the way of evaluating stuff, e.g., `new X.Y` will try to initialise an `X.Y` (so, the Y property of the X object), while `(new X).Y` will initialise an X and get its Y property. You can nest other expressions in the grouping operator but it doesn't really change what's assignable or not `(X, Y)` will invoke the comma operator and thus give you the *value* of `Y` and values aren't assignable. It happens that you cannot otherwise do the same without brackets but `4 = "foo"` is comparable. – VLAZ Feb 18 '21 at 09:53

1 Answers1

4

The relevant bit of the specification is here:

It is a Syntax Error if AssignmentTargetType of LeftHandSideExpression is not simple.

and here.

The simplified version is that (if we leave destructuring aside) you can assign a value to a variable or to a property of an object.

Given (foo), the parenthesis are pointless and the expression is just a variable name. This is fine.

Given (foo1 && foo2 && foo3) the values are read from the variables, compared using the && operator and the outcome is a value.

You can't assign a value to a value, only to a property or a variable.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • 1
    I was going back and forth through the specs trying to find a reference for how the AssignmentTargetType is determined with brackets until I remembered to look at the definition for the grouping operator. [Surrounding an expression in brackets returns its AssignmentTargetType](https://262.ecma-international.org/#sec-grouping-operator-static-semantics-assignmenttargettype). So, it's actually simpler than I thought it was, just scattered in three places - `(foo)` is the same as `foo` and that's a simple assignment target. Hence, `(foo)` is assignable. – VLAZ Feb 18 '21 at 09:28