Reputation: 55
I have a question regarding a code snippet from the React.js
tutorial. I'm a beginner in JavaScript, so please excuse me if this is a dumb question.
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
The purpose of this function is to evaluate the winner of a tic-tac-toe game. The square argument gets an array of nine values with type of null
, "X"
or "O"
.
Assuming that the first three values of the array are "X"
, the if-statement would resolve to "X" && "X" === "X" && "X" === "X"
. This would result in "X" === "X" === "X"
. So it should return true
and the player playing with the "X" has won.
But if I try it in JSBin for example, console.log("X" === "X" === "X")
returns false
. I just don't get it, because in my opinion "X"
is equal to "X"
is equal to "X"
.
Can anyone explain where my error in reasoning is?
Thank you very much!
Sebastian Beier
Upvotes: 3
Views: 79
Reputation: 55
Thank you all very much for your answers! They all helped me a lot!
Now I think I got it.
To test equality of three items, always use the && operator like this: a === b && >b === c.
This is indeed easier to understand than the solution from the React tutorial, at least for me.
Upvotes: 0
Reputation: 1075895
Assuming that the first three values of the array are "X", the if-statement would resolve to "X" && "X" === "X" && "X" === "X". This would result in "X" === "X" === "X".
No, it would result in "X" && true && true
:
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c])
// ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
// "X" true true
The &&
evaluates its left-hand operand and, if that result is falsy¹, results in that falsy value. If the left-hand operand's value is truthy, &&
evalutes its right-hand operand and takes that value as its result.
So "X" && true && true
evalutes to true && true
which evalutes to true
.
In contrast, the ===
operator evalutes its left-hand operand, then its right-hand operand, and then its right-hand operand, and compares the result for strict equality (same type and value). It's also left-to-right associative, so "X" === "X" === "X"
is ("X" === "X") === "X"
which is true === "X"
which is false
, because true
is not strictly equal to "X"
.
¹ "falsy" - When used in a boolean context (for instance, an if
condition) a value is falsy if it coerces to false
. The falsy values are 0
, ""
, null
, undefined
, NaN
, and of course false
. All other values are truthy — they coerce to true
.
Upvotes: 8
Reputation: 1794
Your reasoning around the &&
operator is correct.
The problem is your understanding of the ===
operator. In mathematics you could use equality in the manner you expected (x = x = x) and you would have a correct (true) statement. But in programming it doesn't work like this.
Each operator is evaluated one-by-one.
So you started with:
"X" === "X" === "X"
This will be evaluated as two separate statements. The operator on the left is evaluated first for this operator (this is known as the associativity of the operator). You can put brackets around the first statement to make it explicit, like this:
("X" === "X") === "X"
The statement in the brackets is evaluated, leaving:
true === "X"
This now evaluates to false
, because true
is not equal to "X"
.
I recommend you never try to use the equality operators in this way (a === b === c
). The same goes for other equality operators such as !==
. It's not a typical programming pattern and is likely to confuse other programmers in the same way that it confused you.
To test equality of three items, always use the &&
operator like this: a === b && b === c
. This makes it clear that each equality test happens one-by-one.
Upvotes: 0
Reputation: 175098
Because ===
is a binary operator (it works on two operands at a time, only).
"X" === "X" === "X"
is equivalent to
(("X" === "X") === "X")
(First, the first ===
is evaluated between the first two operands, then the result is compared to the third operand.)
That is equivalent to
true === "X"
Which is, of course, false
.
If you wanted to test the correctness of your logical expression, you would need to replicate it fully, &&
s and all:
console.log("X" && "X" === "X" && "X" === "X"); // true
Upvotes: 4