Example of expression where the precedence of AND (&&) over OR (||) matters? - javascript

In all of the JavaScript operator precedence charts I can find (like this one and this one), the logical AND (&&) has slightly higher precedence to the logical OR (||).
I can't seem to figure out an expression where the result is different than it would be if they had the same precedence. I figure there must be some way for it to matter or they'd be listed as having the same precedence if it didn't.
For example:
0 || 2 && 0 || 3
is 3, but it doesn't matter how I slice that up, it's always going to be 3:
(0 || 2) && 0 || 3
0 || (2 && 0) || 3
(0 || 2 && 0) || 3
0 || 2 && (0 || 3)
0 || (2 && 0 || 3)
If I make that first 0 something else (like 4), the result is always 4 because the first || doesn't even look at the right-hand side. If I swap the 0 and 3 in the last || around, the result remains 3.
The closest I've come is
0 || false && "" || NaN
...which is NaN, whereas
0 || false && ("" || NaN)
...is false, but I think that's explained purely by the left-to-right semantics, not by && being higher precedence.
I must just be missing it, for what expression does it matter that && has a higher precedence than ||?

true || false && false
is true
(true || false) && false
is false
true || (false && false)
is true

If they had the same precedence and were left-associative, then e.g. the expression
1 || 0 && 2
would be
((1 || 0) && 2) // evaluates to 2
instead of the
(1 || (0 && 2)) // evaluates to 1
that we get from the "usual" precedence rules.
For your structure … || … && … || … (which would be (((… || …) && …) || …) instead of normal ((… || (… && …)) || …)), you'd get different results for values like 0 0 1 0.
Why does the logical AND have slightly higher precedence to the logical OR?
So that the canonical form of boolean expressions, the disjunctive normal form, does not need any parenthesis.

Example:
1 || 0 && 0 -> (1 || 0) && 0 -> (1) && 0 -> 0
1 || 0 && 0 -> 1 || (0 && 0) -> 1 || (0) -> 1

Related

Having issues trying to fix this control flow problem

I've thought I figured out how basic javascript logic works, but here I must have forgot something.
let firstElementSavedIndex = 1
console.log(firstElementSavedIndex)
firstElementSavedIndex = 0;
console.log(firstElementSavedIndex)
if (firstElementSavedIndex !== undefined || firstElementSavedIndex !== 0) firstElementSavedIndex -= 1;
console.log(firstElementSavedIndex)
The code I created above I wanted to use as a guard to prevent firstElementSavedIndex from decrementing unless firstElementSavedIndex isn't undefined or 0.
However the code above decrements even if firstElementSavedIndex is 0.
I must be missing something basic, but I havent found any solutions so far.
Any help would be appreciated.
-Hendrik
In the if block the expression becomes
0 !== undefined || 0 !== 0
true || 0 !== 0
true
Since you are using or as long something evaluates to true the whole expression will become true hence the code goes inside the if block.
To fix this you need to replace || with && and make the conditional as savedIndex greater than 0.
let firstElementSavedIndex = 1;
console.log(firstElementSavedIndex);
firstElementSavedIndex = 0;
console.log(firstElementSavedIndex);
if (firstElementSavedIndex !== undefined && firstElementSavedIndex > 0) {
firstElementSavedIndex -= 1;
}
console.log(firstElementSavedIndex);
now it becomes
0 !== undefined && 0 > 0
true && 0 > 0
true && false
false

What is the difference between && and || in JavaScript term?

My classmate used "||" instead of "&&" for an if statement, but the result is the same. I tried to understand the differences by reading the article but I can't seem to understand them. I would appreciate if anyone can explain in an easy way...Thank you!
&& is and operator and || is or operator
&& work as
1 && 1= 1
1 && 0 = 0
0 && 1 = 0
0 && 0 = 0
|| work as
1 || 1= 1
1 || 0 = 1
0 || 1 = 1
0 || 0 = 0
where 1 , 0 are true and false
we can understand it by the following example
suppose we have a code
if(1==1 && 2==2){}
so 1==1 is true means 1 and 2==2 is true means 1, so && operator work like this
1 && 1 =1 hence the result will be true and execute if statement
You could replace logical OR || with logical AND && and vice versa, by using De Morgan's laws:
!(a && b) = !a || !b
!(a || b) = !a && !b
If you have
if (a || b)
you could use this without OR
if (!(!a && !b))

JS Logical And / Or

Can someone explain to me why both of these alert 'True'? The logical OR makes sense I think - The OR short circuits after the first test: 100 != 90, therefor it is true. By why does the AND short circuit after the first test and not keep going?
if (100 != 90 && 100 && 190 && 200 && 290){
alert("true");
} else {
alert("false");
}
if (100 != 90 || 100 || 190 || 200 || 290){
alert("true");
} else {
alert("false");
}
EDIT: THANK YOU EVERYONE FOR YOUR HELP! BASED ON YOUR SUGGESTIONS, I THINK I WILL AMMEND MY CODE TO THIS:
var trains = [90,100,190,200,290];
var testValue = 100;
if (trains.indexOf(testValue) >= 0){
alert("true");
}
This will evaluate to true:
if (100 != 90 && 100 && 190 && 200 && 290)
Because each part is truthy. Any non-zero value in javascript is consider to be equivalent to true. So you have:
if (true && true && true && true && true)
Which is, obviously, true. It's not short circuiting, because none of the values are false.
I suspect the mistake you've made is to think that this:
if (100 != 90 && 100)
Is doing the same thing as this:
if (100 != 90 && 100 != 100)
Which is simply not how the syntax works. It's easy to say in words "if 100 doesn't equal 90 and doesn't equal 100" and understand what that means, but in javascript (and most other languages) you have to be explicit.
Now obviously this gets really tedious if you have a value that you need to compare with a long list of values, for example:
if (x != 90 && x != 100 && x != 190...)
And in a case like that, it's usually easier to put all your values into an array and instead ask if x is contained (or not) in that array:
var values = [90,100,190,...]
if (!values.some(function(e) { return e === x; })) {
// the value x is not in the array values
}
For the &&, the first 100 != 90 evaluates to true. Then, the integers are implicitly converted to bools, where 0 = false, true otherwise. The true will carry through the numbers, of which none are 0.
Your comment about || is correct.

Multiple Sets of Sets of ORs

I have a feeling this isn't possible? I'm trying to check sets of conditions here and my tests should be passing after I moved a couple of those sets out of 2 other methods and into this if statement below as to combine all the checks into one if statement:
if ((move.coordinates.x === 0 && move.coordinates.y === 0 ||
move.coordinates.x === 0 && move.coordinates.y === 1 ||
move.coordinates.x === 0 && move.coordinates.y === 2)
||
(move.coordinates.x === 1 && move.coordinates.y === 0 ||
move.coordinates.x === 1 && move.coordinates.y === 1 ||
move.coordinates.x === 1 && move.coordinates.y === 2)
||
(move.coordinates.x === 2 && move.coordinates.y === 0 ||
move.coordinates.x === 2 && move.coordinates.y === 1 ||
move.coordinates.x === 2 && move.coordinates.y === 2))
{
...then do something
}
Doesn't seem the parens are making a difference here in separating out the conditional sets.
I'm trying to trim down on duplicate code I had those 3 sets in different methods where the logic was mostly the same, but checked for different states.
So I pasted in the two other state sets (sets meaning the group of 3 ors that make up a given state) and trying to check these 3 rows basically in one method instead of splitting out into 3 to cut down dup code.
Simplifying the notation, you have
(x == 0 && y == 0 || x == 0 && y == 1 || x == 0 && y == 2)
||
(x == 1 && y == 0 || x == 1 && y == 1 || x == 1 && y == 2)
||
(x == 2 && y == 0 || x == 2 && y == 1 || x == 2 && y == 2)
Since the operator || is associative, you can remove the parentheses.
And then you can use the distributive property to group the x.
x == 0 && (y == 0 || y == 1 || y == 2) ||
x == 1 && (y == 0 || y == 1 || y == 2) ||
x == 2 && (y == 0 || y == 1 || y == 2)
And even use the distributive property again
(x == 0 || x == 1 || x == 2) && (y == 0 || y == 1 || y == 2)
Finally, you can store the allowed values in an array and use indexOf to avoid repeating the variables:
var values = [0, 1, 2];
values.indexOf(x) >= 0 && values.indexOf(y) >= 0;
you can use logical rules that cover all the possibilities you allow. if you look at the repeating values in your code, you see that you are trying to exhaust all combinations of x values 0,1,2 with combinations of y values 0,1,2. so if you make a rule that will encompass x values from 0 to 2 and the same with y values from 0 to 2, you can simplify your if statement like the example below.
var coordx = move.coordinates.x;
var coordy = move.coordinates.y;
if ((coordx >= 0 && coordx <= 2) && (coordy >= 0 && coordy <=2)) {
// do something
}
One issue I see with your code is the order of operations (take a look here to see the basics), consider using more brackets to be as explicit as possible. It looks like you want to do this:
if (( (move.coordinates.x === 0 && move.coordinates.y === 0) ||
(move.coordinates.x === 0 && move.coordinates.y === 1) ||
(move.coordinates.x === 0 && move.coordinates.y === 2))
||
...
But, if you want to be a little more efficient and clear, I would recommend reformatting your logic with nested if statements:
if (x==0 || x==1 || x==2)
{
if(y==0 || y==1 || y==2)
{
do something...

How does (A == B == C) comparison work in JavaScript?

I was expecting the following comparison to give an error:
var A = B = 0;
if(A == B == 0)
console.log(true);
else
console.log(false);
but strangely it returns false.
Even more strangely,
console.log((A == B == 1));
returns true.
How does this "ternary" kind of comparison work?
First, we need to understand that a == comparison between a number and a boolean value will result in internal type conversion of Boolean value to a number (true becomes 1 and false becomes 0)
The expression you have shown is evaluated from left to right. So, first
A == B
is evaluated and the result is true and you are comparing true with 0. Since true becomes 1 during comparison, 1 == 0 evaluates to false. But when you say
console.log((A == B == 1));
A == B is true, which when compared with number, becomes 1 and you are comparing that with 1 again. That is why it prints true.
Assignment operators like = are right-associative: when there is a series of these operators that have the same precedence, they are processed right-to-left, so A = B = 0 is processed as A = (B = 0) (B = 0 returns 0, so both A and B end up as 0).
Equality operators like == are left-associative: same-precedence operators are processed left-to-right. A == B == 0 is processed as (A == B) == 0, and since A == B is true (1), it becomes 1 == 0, which is false (0).
Likewise, A == B == 1 is processed as (A == B) == 1, which becomes 1 == 1, which is true (1).
Source and more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
First, A == B returns true, which is then compared to 0, true == 0 which returns false, or true == 1 which returns true.
It first checks your clause for A == B, which is true, than it starts checking true == 0, and 0 is false. So when you check A == B == 1, you check A==B, which is true, and true == 1. So then it returns true. If you really want to check all possibilities you should do something like this:
if((A==B) && (A==0))
console.log(true);
else
console.log(false);
if((A == B)&& (A== 0)&& (B==0))
console.log(true);
else
console.log(false);
You can work from left to right. In this case you first check if A == B, then you check if this equal to 0. So since A == B, this is true. So now it becomes (true == 0), which is false. If A=1, B=2, then (A == B == 0) would return true! This is because A == B is false and (false == 0) is true!

Categories

Resources