"Invalid left-hand side in assignment" appears in a strange situation

I have two variables a (can be undefined or Object) and b (Object).

If a.foo exists, I want to set b.foo value. For this I wanted to use a single line expression, using && operators.

Let's look at the example:

> a = {foo:'bar'}
{ foo: 'bar' }
> b = {}
{}
> c = {}
{}
> c.foo = a.foo // returns 'bar'
'bar'
> a && a.foo
'bar'
> a && a.foo && b.foo = a.foo // why doesn't this work?
ReferenceError: Invalid left-hand side in assignment
    at repl:1:1
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)
    at Interface._ttyWrite (readline.js:760:14)
    at ReadStream.onkeypress (readline.js:99:10)
    at ReadStream.emit (events.js:98:17)
    at emitKey (readline.js:1095:12)

I don't understand why b.foo = a.foo in this expression throws the error.

However, the following expressions work:

> a && a.foo && console.log("bar")
bar
undefined
> a && a.foo && (function () {return 'bar'})()
'bar'
> a && a.foo && (function () {b.foo = a.foo;})()
undefined
> b
{ foo: 'bar' }

Why? What's the explanation for this behavior?

You need to encapsulate the expression in (),

a && a.foo && (b.foo = a.foo)

Otherwise it will evaluate the comparison operations first before the assignment operations so it will evaluate as (order of precedence)

(a && a.foo && b.foo) = a.foo;
//or basically
true = a.foo //or false/undefined or whatever depending on what a,a.foo equal

If you take a look at the order of precedence at MDN you will see that the assignment operator is 17th (third from last) in the order, so it gets evaluated nearly after all other operations.

I think that is because expression

a && a.foo && b.foo

returns undefined, and you are saying

a && a.foo && b.foo = a.foo 

so it is same as saying

undefined = a.foo 

which is invalid

You can assign a value to a variable not a value.

And in the following statement

a && a.foo && (function () {b.foo = a.foo;})()

you are saying if a & a.foo is true/someval then you will execute e function. So here it is possible.

The fact is we have to consider operator precedence in javascript.

Check here

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

and operator (&&) has higher precedence over assignment (=) operator. So your all && operation executes before the = operation. but you need = to be happening first. so putting parenthesis will solve the issue as it has higher precedence.

so the solution would be
a && a.foo && (b.foo = a.foo)