Having issues trying to fix this control flow problem - javascript

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

Related

Which is right way to use below statement performance wise?

Which approach is most recommended. First or Second ?
var x = document.querySelectorAll("span");
// #1: Console returns false
x.length > 0 && x[0].blur();
// #2: Console returns undefined
if (x.length > 0) {
x[0].blur();
}
If you find x.length > 0 then you will definitely get x[0] and do not need to check && x[0].blur();. So your second approach is much better.
if (x.length > 0) {
x[0].blur();
}

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.

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

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

JavaScript if statement evaluates only first condition

My if statement evaluates only 1st condition, second one after || is overlooked. How to fix this?
function validateAge(input) {
if ((input.value < 0 || input.value > 110) || (input.value.match(/[^0-9]/))) {
input.setCustomValidity("Dozwolony zakres: od 0 do 110");
} else {
input.setCustomValidity("");
}
}
Well, there is something called lazy evaluation. The JavaScript interpreter won't evaluate something if it is unnecessary to do so. In the disjunction (||) when the first statement evaluates to true then the whole expression is true, so that's why when the JavaScript interpreter evaluates: (input.value < 0 || input.value > 110) to true, it is not necessary to calculate the value of (input.value < 0 || input.value > 110).
If (input.value.match(/[^0-9]/)) is "show stopper" you can proceed the following way:
if ((input.value.match(/[^0-9]/)) || (input.value < 0 || input.value > 110))
If I understood correctly you need something like:
function validateValue(input) {
var value = input.value;
if (/^\d+$/.test(value)) {
value = parseInt(value, 10);
} else {
return false;
}
return value < 0 || value > 110;
}

What does shorthand "index >= 0 && count++" do?

I was killing time reading the underscore.string functions, when I found this weird shorthand:
function count (str, substr) {
var count = 0, index;
for (var i = 0; i < str.length;) {
index = str.indexOf(substr, i);
index >= 0 && count++; //what is this line doing?
i = i + (index >= 0 ? index : 0) + substr.length;
}
return count;
}
Legal: Think twice before using the function above without giving credit to underscore.string
I put the line alone here, so you don't waste time finding it:
index >= 0 && count++;
I have never seen anything similar to that. I am clueless in what is doing.
index >= 0 && count++;
First part: index >= 0
returns true if index has a value that is greater than or equal to 0.
Second part: a && b
most C-style languages shortcut the boolean || and && operators.
For an || operation, you only need to know that the first operand is true and the entire operation will return true.
For an && operation, you only need to know that the first operand is false and the entire operation will return false.
Third Part: count++
count++ is equivalent to count += 1 is equivalent to count = count + 1
All together now
If the first operand (index >= 0) of the line evaluates as true, the second operand (count++) will evaluate, so it's equivalent to:
if (index >= 0) {
count = count + 1;
}
JavaScript nuances
JavaScript is different from other C-style languages in that it has the concept of truthy and falsey values. If a value evaluates to false, 0, NaN, "", null, or undefined, it is falsey; all other values are truthy.
|| and && operators in JavaScript don't return boolean values, they return the last executed operand.
2 || 1 will return 2 because the first operand returned a truthy value, true or anything else will always return true, so no more of the operation needs to execute. Alternatively, null && 100 will return null because the first operand returned a falsey value.
It's equivalent to:
if (index >= 0) {
count = count + 1;
}
&& is the logical AND operator. If index >= 0 is true, then the right part is also evaluated, which increases count by one.
If index >= 0 is false, the right part is not evaluated, so count is not changed.
Also, the && is slightly faster than the if method, as seen in this JSPerf.
It's the same as:
if(index >= 0){
count++;
}
JavaScript will evaluate the left side (index >= 0), if it's false the && (AND) will short circuit (since false AND anything is false), thus not running `count++.
If it's (index >= 0) true, it evaluates the right side (count++), then it just ignores the output.

Categories

Resources