36

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?

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Kevin
  • 383
  • 1
  • 3
  • 5

3 Answers3

63

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!');
}
Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
  • 2
    for clarification, what would the difference be between == and ===? – Kevin Sep 03 '13 at 17:23
  • The above comment is sort of wrong, ECMA specifies that this is not a type check, it does an operation called type coercion. This is really useful to know, see this answer http://stackoverflow.com/questions/19915688/what-exactly-is-type-coercion-in-javascript – VladNeacsu Sep 07 '15 at 06:45
  • @Kevin https://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons – Grant Aug 03 '18 at 17:46
11

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 of getFoo().theAnswer = 42 or array indexing getArray() = 42 instead of getArray()[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...

Community
  • 1
  • 1
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
0

The same happened for me with eslint module. EsLinter throw Parsing error: Invalid left-hand side in assignment expression for await in second if statement.

if (condition_one) {
  let result = await myFunction()
}

if (condition_two) {
  let result = await myFunction() // eslint parsing error
}

As strange as it sounds what fixed this error was to add ; semicolon at the end of line where await occurred.

if (condition_one) {
  let result = await myFunction();
}

if (condition_two) {
  let result = await myFunction();
}
Lukasz Dynowski
  • 11,169
  • 9
  • 81
  • 124