ReferenceError: Invalid left-hand side in assignment
my code for a rock paper scissors game (called toss) is as follows:
var toss = function (one,two) {
if(one = "rock" && two = "rock") {
console.log("Tie! Try again!");
}
// more similar conditions with `else if`
};
When I enter in the parameters
toss("rock","rock")
I get this error code:
"ReferenceError: Invalid left-hand side in assignment"
How to fix it? What this error means and what other cases when this error can happen?
Solution 1:
You have to use ==
to compare (or even ===
, if you want to compare types). A single =
is for assignment.
if (one == 'rock' && two == 'rock') {
console.log('Tie! Try again!');
}
Solution 2:
Common reasons for the error:
- use of assignment (
=
) instead of equality (==
/===
) - assigning to result of function
foo() = 42
instead of passing arguments (foo(42)
) - simply missing member names (i.e. assuming some default selection) :
getFoo() = 42
instead ofgetFoo().theAnswer = 42
or array indexinggetArray() = 42
instead ofgetArray()[0]= 42
In this particular case you want to use ==
(or better ===
- What exactly is Type Coercion in Javascript?) to check for equality (like if(one === "rock" && two === "rock")
, but it the actual reason you are getting the error is trickier.
The reason for the error is Operator precedence. In particular we are looking for &&
(precedence 6) and =
(precedence 3).
Let's put braces in the expression according to priority - &&
is higher than =
so it is executed first similar how one would do 3+4*5+6
as 3+(4*5)+6
:
if(one= ("rock" && two) = "rock"){...
Now we have expression similar to multiple assignments like a = b = 42
which due to right-to-left associativity executed as a = (b = 42)
. So adding more braces:
if(one= ( ("rock" && two) = "rock" ) ){...
Finally we arrived to actual problem: ("rock" && two)
can't be evaluated to l-value that can be assigned to (in this particular case it will be value of two
as truthy).
Note that if you'd use braces to match perceived priority surrounding each "equality" with braces you get no errors. Obviously that also producing different result than you'd expect - changes value of both variables and than do &&
on two strings "rock" && "rock"
resulting in "rock"
(which in turn is truthy) all the time due to behavior of logial &&:
if((one = "rock") && (two = "rock"))
{
// always executed, both one and two are set to "rock"
...
}
For even more details on the error and other cases when it can happen - see specification:
Assignment
LeftHandSideExpression = AssignmentExpression
...
Throw a SyntaxError exception if the following conditions are all true:
...
IsStrictReference(lref) is true
Left-Hand-Side Expressions
and The Reference Specification Type explaining IsStrictReference:
... function calls are permitted to return references. This possibility is admitted purely for the sake of host objects. No built-in ECMAScript function defined by this specification returns a reference and there is no provision for a user-defined function to return a reference...