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)